2 // rootcontext.cs: keeps track of our tree representation, and assemblies loaded.
4 // Author: Miguel de Icaza (miguel@ximian.com)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
11 using System.Collections;
12 using System.Reflection;
13 using System.Reflection.Emit;
14 using System.Diagnostics;
16 namespace Mono.CSharp {
18 public class RootContext {
21 // Contains the parsed tree
26 // Contains loaded assemblies and our generated code as we go.
28 static public TypeManager TypeManager;
31 // The System.Reflection.Emit CodeGenerator
35 static public bool Optimize;
38 // The module builder pointer.
40 static ModuleBuilder mb;
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.
47 static bool stdlib = true;
50 // This keeps track of the order in which classes were defined
51 // so that we can poulate them in that order.
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,
58 static ArrayList type_container_resolve_order;
59 static ArrayList interface_resolve_order;
62 // Holds a reference to the Private Implementation Details
65 static TypeBuilder impl_details_class;
67 public static int WarningLevel = 4;
75 TypeManager = new TypeManager ();
78 static public Tree Tree {
84 static public string MainClass;
86 static public CodeGen CodeGen {
93 // Temporary hack, we should probably
94 // intialize `cg' rather than depending on
95 // external initialization of it.
98 mb = cg.ModuleBuilder;
102 public static void RegisterOrder (Interface iface)
104 interface_resolve_order.Add (iface);
107 public static void RegisterOrder (TypeContainer tc)
109 type_container_resolve_order.Add (tc);
113 // The default compiler checked state
115 static public bool Checked = false;
118 // Whether to allow Unsafe code
120 static public bool Unsafe = false;
122 static string MakeFQN (string nsn, string name)
124 string prefix = (nsn == "" ? "" : nsn + ".");
126 return prefix + name;
130 // This function is used to resolve the hierarchy tree.
131 // It processes interfaces, structs and classes in that order.
133 // It creates the TypeBuilder's as it processes the user defined
136 static public void ResolveTree ()
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.
145 TypeContainer root = Tree.Types;
147 ArrayList ifaces = root.Interfaces;
149 interface_resolve_order = new ArrayList ();
151 foreach (Interface i in ifaces)
152 i.DefineInterface (mb);
155 type_container_resolve_order = new ArrayList ();
157 foreach (TypeContainer tc in root.Types)
160 if (root.Delegates != null)
161 foreach (Delegate d in root.Delegates)
162 d.DefineDelegate (mb);
164 if (root.Enums != null)
165 foreach (Enum e in root.Enums)
171 // Closes all open types
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
180 static public void CloseTypes ()
182 TypeContainer root = Tree.Types;
184 ArrayList ifaces = root.Interfaces;
187 foreach (Interface i in ifaces)
190 foreach (TypeContainer tc in root.Types)
193 if (root.Delegates != null)
194 foreach (Delegate d in root.Delegates)
197 if (root.Enums != null)
198 foreach (Enum en in root.Enums)
203 // If we have a <PrivateImplementationDetails> class, close it
205 if (impl_details_class != null){
206 impl_details_class.CreateType ();
211 // Public function used to locate types, this can only
212 // be used after the ResolveTree function has been invoked.
214 // Returns: Type or null if they type can not be found.
216 static public Type LookupType (DeclSpace ds, string name, bool silent)
220 t = TypeManager.LookupType (MakeFQN (ds.Namespace.Name, name));
224 // It's possible that name already is fully qualified. So we do
225 // a simple direct lookup without adding any namespace names
227 t = TypeManager.LookupType (name);
231 for (Namespace ns = ds.Namespace; ns != null; ns = ns.Parent){
232 ArrayList using_list = ns.UsingTable;
234 if (using_list == null)
237 foreach (string n in using_list){
238 t = TypeManager.LookupType (MakeFQN (n, name));
244 // For the case the type we are looking for is nested within this one.
245 t = TypeManager.LookupType (ds.Name + "." + name);
250 Report.Error (246, "Cannot find type `"+name+"'");
256 // This is the silent version of LookupType, you can use this
257 // to `probe' for a type
259 static public Type LookupType (TypeContainer tc, string name)
261 return LookupType (tc, name, true);
264 static public bool IsNamespace (string name)
268 if (tree.Namespaces != null){
269 ns = (Namespace) tree.Namespaces [name];
278 static void Report1530 (Location loc)
280 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
284 // Populates the structs and classes with fields and methods
287 // This is invoked after all interfaces, structs and classes
288 // have been defined through `ResolveTree'
289 static public void PopulateTypes ()
291 TypeContainer root = Tree.Types;
293 if (interface_resolve_order != null){
294 foreach (Interface iface in interface_resolve_order)
295 if ((iface.ModFlags & Modifiers.NEW) == 0)
298 Report1530 (iface.Location);
302 if (type_container_resolve_order != null){
303 foreach (TypeContainer tc in type_container_resolve_order)
304 if ((tc.ModFlags & Modifiers.NEW) == 0)
307 Report1530 (tc.Location);
310 ArrayList delegates = root.Delegates;
311 if (delegates != null){
312 foreach (Delegate d in delegates)
313 if ((d.ModFlags & Modifiers.NEW) == 0)
316 Report1530 (d.Location);
319 ArrayList enums = root.Enums;
321 foreach (Enum en in enums)
322 if ((en.ModFlags & Modifiers.NEW) == 0)
325 Report1530 (en.Location);
329 static public void EmitCode ()
331 if (type_container_resolve_order != null)
332 foreach (TypeContainer tc in type_container_resolve_order)
337 // Compiling against Standard Libraries property.
339 static public bool StdLib {
349 static public ModuleBuilder ModuleBuilder {
356 // Public Field, used to track which method is the public entry
359 static public MethodInfo EntryPoint;
362 // These are used to generate unique names on the structs and fields.
364 static int field_count;
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.
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
376 // 1. DefineNestedType on the impl_details_class with our struct.
378 // 2. Define the field on the impl_details_class
380 static public FieldBuilder MakeStaticData (byte [] data)
383 int size = data.Length;
385 if (impl_details_class == null)
386 impl_details_class = mb.DefineType (
387 "<PrivateImplementationDetails>", TypeAttributes.NotPublic);
389 fb = impl_details_class.DefineInitializedData (
390 "$$field-" + (field_count++), data,
391 FieldAttributes.Static | FieldAttributes.Assembly);