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 // The list of global attributes (those that target the assembly)
45 static Attributes global_attributes;
48 // Whether we are being linked against the standard libraries.
49 // This is only used to tell whether `System.Object' should
50 // have a parent or not.
52 public static bool StdLib = true;
55 // This keeps track of the order in which classes were defined
56 // so that we can poulate them in that order.
58 // Order is important, because we need to be able to tell by
59 // examining the parent's list of methods which ones are virtual
60 // or abstract as well as the parent names (to implement new,
63 static ArrayList type_container_resolve_order;
64 static ArrayList interface_resolve_order;
67 // Holds a reference to the Private Implementation Details
70 static TypeBuilder impl_details_class;
72 public static int WarningLevel = 2;
80 TypeManager = new TypeManager ();
83 static public Tree Tree {
89 static public string MainClass;
91 static public CodeGen CodeGen {
98 // Temporary hack, we should probably
99 // intialize `cg' rather than depending on
100 // external initialization of it.
103 mb = cg.ModuleBuilder;
107 public static void RegisterOrder (Interface iface)
109 interface_resolve_order.Add (iface);
112 public static void RegisterOrder (TypeContainer tc)
114 type_container_resolve_order.Add (tc);
118 // The default compiler checked state
120 static public bool Checked = false;
123 // Whether to allow Unsafe code
125 static public bool Unsafe = false;
127 static string MakeFQN (string nsn, string name)
129 string prefix = (nsn == "" ? "" : nsn + ".");
131 return prefix + name;
135 // This function is used to resolve the hierarchy tree.
136 // It processes interfaces, structs and classes in that order.
138 // It creates the TypeBuilder's as it processes the user defined
141 static public void ResolveTree ()
144 // Interfaces are processed first, as classes and
145 // structs might inherit from an object or implement
146 // a set of interfaces, we need to be able to tell
147 // them appart by just using the TypeManager.
150 TypeContainer root = Tree.Types;
152 ArrayList ifaces = root.Interfaces;
154 interface_resolve_order = new ArrayList ();
156 foreach (Interface i in ifaces)
157 i.DefineInterface (mb);
160 type_container_resolve_order = new ArrayList ();
162 foreach (TypeContainer tc in root.Types)
165 if (root.Delegates != null)
166 foreach (Delegate d in root.Delegates)
167 d.DefineDelegate (mb);
169 if (root.Enums != null)
170 foreach (Enum e in root.Enums)
176 // Closes all open types
180 // We usually use TypeBuilder types. When we are done
181 // creating the type (which will happen after we have added
182 // methods, fields, etc) we need to "Define" them before we
183 // can save the Assembly
185 static public void CloseTypes ()
187 TypeContainer root = Tree.Types;
189 ArrayList ifaces = root.Interfaces;
191 if (root.Enums != null)
192 foreach (Enum en in root.Enums)
195 if (interface_resolve_order != null){
196 foreach (Interface iface in interface_resolve_order)
201 // We do this in two passes, first we close the structs,
202 // then the classes, because it seems the code needs it this
203 // way. If this is really what is going on, we should probably
204 // make sure that we define the structs in order as well.
206 if (type_container_resolve_order != null){
207 foreach (TypeContainer tc in type_container_resolve_order){
208 if (tc is Struct && tc.Parent == tree.Types){
213 foreach (TypeContainer tc in type_container_resolve_order){
214 if (!(tc is Struct && tc.Parent == tree.Types))
219 if (root.Delegates != null)
220 foreach (Delegate d in root.Delegates)
225 // If we have a <PrivateImplementationDetails> class, close it
227 if (impl_details_class != null){
228 impl_details_class.CreateType ();
233 // Public function used to locate types, this can only
234 // be used after the ResolveTree function has been invoked.
236 // Returns: Type or null if they type can not be found.
238 static public Type LookupType (DeclSpace ds, string name, bool silent, Location loc)
243 // For the case the type we are looking for is nested within this one
246 DeclSpace containing_ds = ds;
247 while (containing_ds != null){
248 Type current_type = containing_ds.TypeBuilder;
250 while (current_type != null) {
251 t = TypeManager.LookupType (current_type.FullName + "+" + name);
254 current_type = current_type.BaseType;
257 containing_ds = containing_ds.Parent;
260 t = TypeManager.LookupType (MakeFQN (ds.Namespace.Name, name));
264 // It's possible that name already is fully qualified. So we do
265 // a simple direct lookup without adding any namespace names
267 t = TypeManager.LookupType (name);
271 for (Namespace ns = ds.Namespace; ns != null; ns = ns.Parent){
272 ArrayList using_list = ns.UsingTable;
274 if (using_list == null)
277 foreach (string n in using_list){
278 t = TypeManager.LookupType (MakeFQN (n, name));
285 Report.Error (246, loc, "Cannot find type `"+name+"'");
291 // This is the silent version of LookupType, you can use this
292 // to `probe' for a type
294 static public Type LookupType (TypeContainer tc, string name, Location loc)
296 return LookupType (tc, name, true, loc);
299 static public bool IsNamespace (string name)
303 if (tree.Namespaces != null){
304 ns = (Namespace) tree.Namespaces [name];
313 static void Report1530 (Location loc)
315 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
319 // Populates the structs and classes with fields and methods
322 // This is invoked after all interfaces, structs and classes
323 // have been defined through `ResolveTree'
324 static public void PopulateTypes ()
326 TypeContainer root = Tree.Types;
328 if (interface_resolve_order != null){
329 foreach (Interface iface in interface_resolve_order)
330 if ((iface.ModFlags & Modifiers.NEW) == 0)
333 Report1530 (iface.Location);
337 if (type_container_resolve_order != null){
338 foreach (TypeContainer tc in type_container_resolve_order)
339 if ((tc.ModFlags & Modifiers.NEW) == 0)
342 Report1530 (tc.Location);
345 ArrayList delegates = root.Delegates;
346 if (delegates != null){
347 foreach (Delegate d in delegates)
348 if ((d.ModFlags & Modifiers.NEW) == 0)
351 Report1530 (d.Location);
354 ArrayList enums = root.Enums;
356 foreach (Enum en in enums)
357 if ((en.ModFlags & Modifiers.NEW) == 0)
360 Report1530 (en.Location);
364 static public void EmitCode ()
366 if (type_container_resolve_order != null){
367 foreach (TypeContainer tc in type_container_resolve_order)
370 foreach (TypeContainer tc in type_container_resolve_order)
374 if (global_attributes != null){
375 EmitContext ec = new EmitContext (
376 tree.Types, Mono.CSharp.Location.Null, null, null, 0, false);
377 AssemblyBuilder ab = cg.AssemblyBuilder;
379 Attribute.ApplyAttributes (ec, ab, ab, global_attributes,
380 global_attributes.Location);
384 ConstructorInfo ci = TypeManager.unverifiable_code_type.GetConstructor (new Type [0]);
387 Console.WriteLine ("Internal error !");
391 CustomAttributeBuilder cb = new CustomAttributeBuilder (ci, new object [0]);
392 mb.SetCustomAttribute (cb);
396 static public ModuleBuilder ModuleBuilder {
403 // Public Field, used to track which method is the public entry
406 static public MethodInfo EntryPoint;
409 // These are used to generate unique names on the structs and fields.
411 static int field_count;
414 // Makes an initialized struct, returns the field builder that
415 // references the data. Thanks go to Sergey Chaban for researching
416 // how to do this. And coming up with a shorter mechanism than I
417 // was able to figure out.
419 // This works but makes an implicit public struct $ArrayType$SIZE and
420 // makes the fields point to it. We could get more control if we did
423 // 1. DefineNestedType on the impl_details_class with our struct.
425 // 2. Define the field on the impl_details_class
427 static public FieldBuilder MakeStaticData (byte [] data)
430 int size = data.Length;
432 if (impl_details_class == null)
433 impl_details_class = mb.DefineType (
434 "<PrivateImplementationDetails>", TypeAttributes.NotPublic);
436 fb = impl_details_class.DefineInitializedData (
437 "$$field-" + (field_count++), data,
438 FieldAttributes.Static | FieldAttributes.Assembly);
443 static public void AddGlobalAttributes (AttributeSection sect, Location loc)
445 if (global_attributes == null)
446 global_attributes = new Attributes (sect, loc);
448 global_attributes.AddAttribute (sect);