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;
103 // The default compiler checked state
105 static public bool Checked = false;
108 // Whether to allow Unsafe code
110 static public bool Unsafe = false;
112 static string MakeFQN (string nsn, string name)
114 string prefix = (nsn == "" ? "" : nsn + ".");
116 return prefix + name;
120 // This function is used to resolve the hierarchy tree.
121 // It processes interfaces, structs and classes in that order.
123 // It creates the TypeBuilder's as it processes the user defined
126 static public void ResolveTree ()
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.
135 TypeContainer root = Tree.Types;
137 ArrayList ifaces = root.Interfaces;
139 interface_resolve_order = new ArrayList ();
141 foreach (Interface i in ifaces) {
142 Type t = i.DefineInterface (mb);
144 interface_resolve_order.Add (i);
148 type_container_resolve_order = new ArrayList ();
150 foreach (TypeContainer tc in root.Types) {
151 Type t = tc.DefineType (mb);
153 type_container_resolve_order.Add (tc);
156 if (root.Delegates != null)
157 foreach (Delegate d in root.Delegates)
158 d.DefineDelegate (mb);
160 if (root.Enums != null)
161 foreach (Enum e in root.Enums)
167 // Closes all open types
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
176 static public void CloseTypes ()
178 TypeContainer root = Tree.Types;
180 ArrayList ifaces = root.Interfaces;
183 foreach (Interface i in ifaces)
186 foreach (TypeContainer tc in root.Types)
189 if (root.Delegates != null)
190 foreach (Delegate d in root.Delegates)
193 if (root.Enums != null)
194 foreach (Enum en in root.Enums)
199 // If we have a <PrivateImplementationDetails> class, close it
201 if (impl_details_class != null){
202 impl_details_class.CreateType ();
207 // Public function used to locate types, this can only
208 // be used after the ResolveTree function has been invoked.
210 // Returns: Type or null if they type can not be found.
212 static public Type LookupType (DeclSpace ds, string name, bool silent)
216 t = TypeManager.LookupType (MakeFQN (ds.Namespace.Name, name));
220 // It's possible that name already is fully qualified. So we do
221 // a simple direct lookup without adding any namespace names
223 t = TypeManager.LookupType (name);
227 for (Namespace ns = ds.Namespace; ns != null; ns = ns.Parent){
228 ArrayList using_list = ns.UsingTable;
230 if (using_list == null)
233 foreach (string n in using_list){
234 t = TypeManager.LookupType (MakeFQN (n, name));
240 // For the case the type we are looking for is nested within this one.
241 t = TypeManager.LookupType (ds.Name + "." + name);
246 Report.Error (246, "Cannot find type `"+name+"'");
252 // This is the silent version of LookupType, you can use this
253 // to `probe' for a type
255 static public Type LookupType (TypeContainer tc, string name)
257 return LookupType (tc, name, true);
260 static public bool IsNamespace (string name)
264 if (tree.Namespaces != null){
265 ns = (Namespace) tree.Namespaces [name];
275 // Populates the structs and classes with fields and methods
278 // This is invoked after all interfaces, structs and classes
279 // have been defined through `ResolveTree'
280 static public void PopulateTypes ()
282 if (interface_resolve_order != null)
283 foreach (Interface iface in interface_resolve_order)
286 if (type_container_resolve_order != null)
287 foreach (TypeContainer tc in type_container_resolve_order)
290 TypeContainer root = Tree.Types;
292 ArrayList delegates = root.Delegates;
293 if (delegates != null)
294 foreach (Delegate d in delegates)
297 ArrayList enums = root.Enums;
299 foreach (Enum en in enums)
304 static public void EmitCode ()
306 if (type_container_resolve_order != null)
307 foreach (TypeContainer tc in type_container_resolve_order)
312 // Compiling against Standard Libraries property.
314 static public bool StdLib {
324 static public ModuleBuilder ModuleBuilder {
331 // Public Field, used to track which method is the public entry
334 static public MethodInfo EntryPoint;
337 // These are used to generate unique names on the structs and fields.
339 static int field_count;
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.
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
351 // 1. DefineNestedType on the impl_details_class with our struct.
353 // 2. Define the field on the impl_details_class
355 static public FieldBuilder MakeStaticData (byte [] data)
358 int size = data.Length;
360 if (impl_details_class == null)
361 impl_details_class = mb.DefineType (
362 "<PrivateImplementationDetails>", TypeAttributes.NotPublic);
364 fb = impl_details_class.DefineInitializedData (
365 "$$field-" + (field_count++), data,
366 FieldAttributes.Static | FieldAttributes.Assembly);