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