2001-12-19 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                 public static void RegisterOrder (Interface iface)
103                 {
104                         interface_resolve_order.Add (iface);
105                 }
106                 
107                 public static void RegisterOrder (TypeContainer tc)
108                 {
109                         type_container_resolve_order.Add (tc);
110                 }
111                 
112                 // 
113                 // The default compiler checked state
114                 //
115                 static public bool Checked = false;
116
117                 //
118                 // Whether to allow Unsafe code
119                 //
120                 static public bool Unsafe = false;
121                 
122                 static string MakeFQN (string nsn, string name)
123                 {
124                         string prefix = (nsn == "" ? "" : nsn + ".");
125
126                         return prefix + name;
127                 }
128                        
129                 // <remarks>
130                 //   This function is used to resolve the hierarchy tree.
131                 //   It processes interfaces, structs and classes in that order.
132                 //
133                 //   It creates the TypeBuilder's as it processes the user defined
134                 //   types.  
135                 // </remarks>
136                 static public void ResolveTree ()
137                 {
138                         //
139                         // Interfaces are processed first, as classes and
140                         // structs might inherit from an object or implement
141                         // a set of interfaces, we need to be able to tell
142                         // them appart by just using the TypeManager.
143                         //
144
145                         TypeContainer root = Tree.Types;
146
147                         ArrayList ifaces = root.Interfaces;
148                         if (ifaces != null){
149                                 interface_resolve_order = new ArrayList ();
150                                 
151                                 foreach (Interface i in ifaces) 
152                                         i.DefineInterface (mb);
153                         }
154                                                 
155                         type_container_resolve_order = new ArrayList ();
156                         
157                         foreach (TypeContainer tc in root.Types) 
158                                 tc.DefineType (mb);
159
160                         if (root.Delegates != null)
161                                 foreach (Delegate d in root.Delegates) 
162                                         d.DefineDelegate (mb);
163
164                         if (root.Enums != null)
165                                 foreach (Enum e in root.Enums)
166                                         e.DefineEnum (mb);
167                         
168                 }
169                         
170                 // <summary>
171                 //   Closes all open types
172                 // </summary>
173                 //
174                 // <remarks>
175                 //   We usually use TypeBuilder types.  When we are done
176                 //   creating the type (which will happen after we have added
177                 //   methods, fields, etc) we need to "Define" them before we
178                 //   can save the Assembly
179                 // </remarks>
180                 static public void CloseTypes ()
181                 {
182                         TypeContainer root = Tree.Types;
183                         
184                         ArrayList ifaces = root.Interfaces;
185
186                         if (ifaces != null)
187                                 foreach (Interface i in ifaces) 
188                                         i.CloseType ();
189                         
190                         foreach (TypeContainer tc in root.Types)
191                                 tc.CloseType ();
192
193                         if (root.Delegates != null)
194                                 foreach (Delegate d in root.Delegates)
195                                         d.CloseDelegate ();
196
197                         if (root.Enums != null)
198                                 foreach (Enum en in root.Enums)
199                                         en.CloseEnum ();
200                         
201
202                         //
203                         // If we have a <PrivateImplementationDetails> class, close it
204                         //
205                         if (impl_details_class != null){
206                                 impl_details_class.CreateType ();
207                         }
208                 }
209                 
210                 //
211                 // Public function used to locate types, this can only
212                 // be used after the ResolveTree function has been invoked.
213                 //
214                 // Returns: Type or null if they type can not be found.
215                 //
216                 static public Type LookupType (DeclSpace ds, string name, bool silent)
217                 {
218                         Type t;
219                         
220                         t = TypeManager.LookupType (MakeFQN (ds.Namespace.Name, name));
221                         if (t != null)
222                                 return t;
223
224                         // It's possible that name already is fully qualified. So we do
225                         // a simple direct lookup without adding any namespace names
226
227                         t = TypeManager.LookupType (name); 
228                         if (t != null)
229                                 return t;
230                         
231                         for (Namespace ns = ds.Namespace; ns != null; ns = ns.Parent){
232                                 ArrayList using_list = ns.UsingTable;
233
234                                 if (using_list == null)
235                                         continue;
236
237                                 foreach (string n in using_list){
238                                         t = TypeManager.LookupType (MakeFQN (n, name));
239                                         if (t != null)
240                                                 return t;
241                                 }
242                         }
243
244                         // For the case the type we are looking for is nested within this one.
245                         t = TypeManager.LookupType (ds.Name + "." + name);
246                         if (t != null)
247                                 return t;
248                         
249                         if (!silent)
250                                 Report.Error (246, "Cannot find type `"+name+"'");
251                         
252                         return null;
253                 }
254
255                 // <summary>
256                 //   This is the silent version of LookupType, you can use this
257                 //   to `probe' for a type
258                 // </summary>
259                 static public Type LookupType (TypeContainer tc, string name)
260                 {
261                         return LookupType (tc, name, true);
262                 }
263
264                 static public bool IsNamespace (string name)
265                 {
266                         Namespace ns;
267
268                         if (tree.Namespaces != null){
269                                 ns = (Namespace) tree.Namespaces [name];
270
271                                 if (ns != null)
272                                         return true;
273                         }
274
275                         return false;
276                 }
277
278                 static void Report1530 (Location loc)
279                 {
280                         Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
281                 }
282                 
283                 // <summary>
284                 //   Populates the structs and classes with fields and methods
285                 // </summary>
286                 //
287                 // This is invoked after all interfaces, structs and classes
288                 // have been defined through `ResolveTree' 
289                 static public void PopulateTypes ()
290                 {
291                         TypeContainer root = Tree.Types;
292
293                         if (interface_resolve_order != null){
294                                 foreach (Interface iface in interface_resolve_order)
295                                         if ((iface.ModFlags & Modifiers.NEW) == 0)
296                                                 iface.Define (root);
297                                         else
298                                                 Report1530 (iface.Location);
299                         }
300
301
302                         if (type_container_resolve_order != null){
303                                 foreach (TypeContainer tc in type_container_resolve_order)
304                                         if ((tc.ModFlags & Modifiers.NEW) == 0)
305                                                 tc.Define (root);
306                                         else
307                                                 Report1530 (tc.Location);
308                         }
309
310                         ArrayList delegates = root.Delegates;
311                         if (delegates != null){
312                                 foreach (Delegate d in delegates)
313                                         if ((d.ModFlags & Modifiers.NEW) == 0)
314                                                 d.Define (root);
315                                         else
316                                                 Report1530 (d.Location);
317                         }
318
319                         ArrayList enums = root.Enums;
320                         if (enums != null){
321                                 foreach (Enum en in enums)
322                                         if ((en.ModFlags & Modifiers.NEW) == 0)
323                                                 en.Define (root);
324                                         else
325                                                 Report1530 (en.Location);
326                         }
327                 }
328
329                 static public void EmitCode ()
330                 {
331                         if (type_container_resolve_order != null)
332                                 foreach (TypeContainer tc in type_container_resolve_order)
333                                         tc.Emit ();
334                 }
335                 
336                 // <summary>
337                 //   Compiling against Standard Libraries property.
338                 // </summary>
339                 static public bool StdLib {
340                         get {
341                                 return stdlib;
342                         }
343
344                         set {
345                                 stdlib = value;
346                         }
347                 }
348
349                 static public ModuleBuilder ModuleBuilder {
350                         get {
351                                 return mb;
352                         }
353                 }
354
355                 //
356                 // Public Field, used to track which method is the public entry
357                 // point.
358                 //
359                 static public MethodInfo EntryPoint;
360
361                 //
362                 // These are used to generate unique names on the structs and fields.
363                 //
364                 static int field_count;
365                 
366                 //
367                 // Makes an initialized struct, returns the field builder that
368                 // references the data.  Thanks go to Sergey Chaban for researching
369                 // how to do this.  And coming up with a shorter mechanism than I
370                 // was able to figure out.
371                 //
372                 // This works but makes an implicit public struct $ArrayType$SIZE and
373                 // makes the fields point to it.  We could get more control if we did
374                 // use instead:
375                 //
376                 // 1. DefineNestedType on the impl_details_class with our struct.
377                 //
378                 // 2. Define the field on the impl_details_class
379                 //
380                 static public FieldBuilder MakeStaticData (byte [] data)
381                 {
382                         FieldBuilder fb;
383                         int size = data.Length;
384                         
385                         if (impl_details_class == null)
386                                 impl_details_class = mb.DefineType (
387                                         "<PrivateImplementationDetails>", TypeAttributes.NotPublic);
388
389                         fb = impl_details_class.DefineInitializedData (
390                                 "$$field-" + (field_count++), data,
391                                 FieldAttributes.Static | FieldAttributes.Assembly);
392                         
393                         return fb;
394                 }
395         }
396 }
397               
398