01141e47f9aea84a3acecd14ad7e0403dad6f5d6
[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                         if (root.Enums != null)
150                                 foreach (Enum e in root.Enums)
151                                         e.DefineEnum (mb);
152                         
153                 }
154                         
155                 // <summary>
156                 //   Closes all open types
157                 // </summary>
158                 //
159                 // <remarks>
160                 //   We usually use TypeBuilder types.  When we are done
161                 //   creating the type (which will happen after we have added
162                 //   methods, fields, etc) we need to "Define" them before we
163                 //   can save the Assembly
164                 // </remarks>
165                 public void CloseTypes ()
166                 {
167                         TypeContainer root = Tree.Types;
168                         
169                         ArrayList ifaces = root.Interfaces;
170
171                         if (ifaces != null)
172                                 foreach (Interface i in ifaces) 
173                                         i.CloseType ();
174                         
175                         foreach (TypeContainer tc in root.Types)
176                                 tc.CloseType ();
177
178                         if (root.Delegates != null)
179                                 foreach (Delegate d in root.Delegates)
180                                         d.CloseDelegate ();
181
182                         if (root.Enums != null)
183                                 foreach (Enum en in root.Enums)
184                                         en.CloseEnum ();
185                         
186
187                         //
188                         // If we have a <PrivateImplementationDetails> class, close it
189                         //
190                         if (impl_details_class != null){
191                                 impl_details_class.CreateType ();
192                         }
193                 }
194                 
195                 //
196                 // Public function used to locate types, this can only
197                 // be used after the ResolveTree function has been invoked.
198                 //
199                 // Returns: Type or null if they type can not be found.
200                 //
201                 public Type LookupType (TypeContainer tc, string name, bool silent)
202                 {
203                         Type t;
204
205                         t = TypeManager.LookupType (MakeFQN (tc.Namespace.Name, name));
206                         if (t != null)
207                                 return t;
208
209                         // It's possible that name already is fully qualified. So we do
210                         // a simple direct lookup without adding any namespace names
211
212                         t = TypeManager.LookupType (name); 
213                         if (t != null)
214                                 return t;
215                         
216                         for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
217                                 ArrayList using_list = ns.UsingTable;
218
219                                 if (using_list == null)
220                                         continue;
221
222                                 foreach (string n in using_list){
223                                         t = TypeManager.LookupType (MakeFQN (n, name));
224                                         if (t != null)
225                                                 return t;
226                                 }
227                         }
228
229                         // For the case the type we are looking for is nested within this one.
230                         t = TypeManager.LookupType (tc.Name + "." + name);
231                         if (t != null)
232                                 return t;
233                         
234                         if (!silent)
235                                 Report.Error (246, "Cannot find type `"+name+"'");
236                         
237                         return null;
238                 }
239
240                 // <summary>
241                 //   This is the silent version of LookupType, you can use this
242                 //   to `probe' for a type
243                 // </summary>
244                 public Type LookupType (TypeContainer tc, string name)
245                 {
246                         return LookupType (tc, name, true);
247                 }
248
249                 public bool IsNamespace (string name)
250                 {
251                         Namespace ns;
252
253                         if (tree.Namespaces != null){
254                                 ns = (Namespace) tree.Namespaces [name];
255
256                                 if (ns != null)
257                                         return true;
258                         }
259
260                         return false;
261                 }
262
263                 // <summary>
264                 //   Populates the structs and classes with fields and methods
265                 // </summary>
266                 //
267                 // This is invoked after all interfaces, structs and classes
268                 // have been defined through `ResolveTree' 
269                 public void PopulateTypes ()
270                 {
271                         if (interface_resolve_order != null)
272                                 foreach (Interface iface in interface_resolve_order)
273                                         iface.Populate ();
274
275                         if (type_container_resolve_order != null)
276                                 foreach (TypeContainer tc in type_container_resolve_order)
277                                         tc.Populate ();
278
279                         TypeContainer root = Tree.Types;
280
281                         ArrayList delegates = root.Delegates;
282                         if (delegates != null)
283                                 foreach (Delegate d in delegates)
284                                         d.Populate (root);
285
286                         ArrayList enums = root.Enums;
287                         if (enums != null)
288                                 foreach (Enum en in enums)
289                                         en.Populate (root);
290                         
291                 }
292
293                 public void EmitCode ()
294                 {
295                         if (type_container_resolve_order != null)
296                                 foreach (TypeContainer tc in type_container_resolve_order)
297                                         tc.Emit ();
298                 }
299                 
300                 // <summary>
301                 //   Compiling against Standard Libraries property.
302                 // </summary>
303                 public bool StdLib {
304                         get {
305                                 return stdlib;
306                         }
307
308                         set {
309                                 stdlib = value;
310                         }
311                 }
312
313                 public ModuleBuilder ModuleBuilder {
314                         get {
315                                 return mb;
316                         }
317                 }
318
319                 //
320                 // Public Field, used to track which method is the public entry
321                 // point.
322                 //
323                 public MethodInfo EntryPoint;
324
325                 //
326                 // These are used to generate unique names on the structs and fields.
327                 //
328                 int field_count;
329                 
330                 //
331                 // Makes an initialized struct, returns the field builder that
332                 // references the data.  Thanks go to Sergey Chaban for researching
333                 // how to do this.  And coming up with a shorter mechanism than I
334                 // was able to figure out.
335                 //
336                 // This works but makes an implicit public struct $ArrayType$SIZE and
337                 // makes the fields point to it.  We could get more control if we did
338                 // use instead:
339                 //
340                 // 1. DefineNestedType on the impl_details_class with our struct.
341                 //
342                 // 2. Define the field on the impl_details_class
343                 //
344                 public FieldBuilder MakeStaticData (byte [] data)
345                 {
346                         FieldBuilder fb;
347                         int size = data.Length;
348                         
349                         if (impl_details_class == null)
350                                 impl_details_class = mb.DefineType (
351                                         "<PrivateImplementationDetails>", TypeAttributes.NotPublic);
352
353                         fb = impl_details_class.DefineInitializedData (
354                                 "$$field-" + (field_count++), data,
355                                 FieldAttributes.Static | FieldAttributes.Assembly);
356                         
357                         return fb;
358                 }
359         }
360 }
361               
362