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 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 ArrayList type_container_resolve_order;
59 ArrayList interface_resolve_order;
62 // Holds a reference to the Private Implementation Details
65 TypeBuilder impl_details_class;
72 tree = new Tree (this);
73 TypeManager = new TypeManager ();
82 public CodeGen CodeGen {
89 // Temporary hack, we should probably
90 // intialize `cg' rather than depending on
91 // external initialization of it.
94 mb = cg.ModuleBuilder;
99 // The default compiler checked state
101 public bool Checked = false;
103 string MakeFQN (string nsn, string name)
105 string prefix = (nsn == "" ? "" : nsn + ".");
107 return prefix + name;
111 // This function is used to resolve the hierarchy tree.
112 // It processes interfaces, structs and classes in that order.
114 // It creates the TypeBuilder's as it processes the user defined
117 public void ResolveTree ()
120 // Interfaces are processed first, as classes and
121 // structs might inherit from an object or implement
122 // a set of interfaces, we need to be able to tell
123 // them appart by just using the TypeManager.
126 TypeContainer root = Tree.Types;
128 ArrayList ifaces = root.Interfaces;
130 interface_resolve_order = new ArrayList ();
132 foreach (Interface i in ifaces) {
133 Type t = i.DefineInterface (mb);
135 interface_resolve_order.Add (i);
139 type_container_resolve_order = new ArrayList ();
141 foreach (TypeContainer tc in root.Types) {
142 Type t = tc.DefineType (mb);
144 type_container_resolve_order.Add (tc);
147 if (root.Delegates != null)
148 foreach (Delegate d in root.Delegates)
149 d.DefineDelegate (mb);
151 if (root.Enums != null)
152 foreach (Enum e in root.Enums)
158 // Closes all open types
162 // We usually use TypeBuilder types. When we are done
163 // creating the type (which will happen after we have added
164 // methods, fields, etc) we need to "Define" them before we
165 // can save the Assembly
167 public void CloseTypes ()
169 TypeContainer root = Tree.Types;
171 ArrayList ifaces = root.Interfaces;
174 foreach (Interface i in ifaces)
177 foreach (TypeContainer tc in root.Types)
180 if (root.Delegates != null)
181 foreach (Delegate d in root.Delegates)
184 if (root.Enums != null)
185 foreach (Enum en in root.Enums)
190 // If we have a <PrivateImplementationDetails> class, close it
192 if (impl_details_class != null){
193 impl_details_class.CreateType ();
198 // Public function used to locate types, this can only
199 // be used after the ResolveTree function has been invoked.
201 // Returns: Type or null if they type can not be found.
203 public Type LookupType (DeclSpace ds, string name, bool silent)
207 t = TypeManager.LookupType (MakeFQN (ds.Namespace.Name, name));
211 // It's possible that name already is fully qualified. So we do
212 // a simple direct lookup without adding any namespace names
214 t = TypeManager.LookupType (name);
218 for (Namespace ns = ds.Namespace; ns != null; ns = ns.Parent){
219 ArrayList using_list = ns.UsingTable;
221 if (using_list == null)
224 foreach (string n in using_list){
225 t = TypeManager.LookupType (MakeFQN (n, name));
231 // For the case the type we are looking for is nested within this one.
232 t = TypeManager.LookupType (ds.Name + "." + name);
237 Report.Error (246, "Cannot find type `"+name+"'");
243 // This is the silent version of LookupType, you can use this
244 // to `probe' for a type
246 public Type LookupType (TypeContainer tc, string name)
248 return LookupType (tc, name, true);
251 public bool IsNamespace (string name)
255 if (tree.Namespaces != null){
256 ns = (Namespace) tree.Namespaces [name];
266 // Populates the structs and classes with fields and methods
269 // This is invoked after all interfaces, structs and classes
270 // have been defined through `ResolveTree'
271 public void PopulateTypes ()
273 if (interface_resolve_order != null)
274 foreach (Interface iface in interface_resolve_order)
277 if (type_container_resolve_order != null)
278 foreach (TypeContainer tc in type_container_resolve_order)
281 TypeContainer root = Tree.Types;
283 ArrayList delegates = root.Delegates;
284 if (delegates != null)
285 foreach (Delegate d in delegates)
288 ArrayList enums = root.Enums;
290 foreach (Enum en in enums)
295 public void EmitCode ()
297 if (type_container_resolve_order != null)
298 foreach (TypeContainer tc in type_container_resolve_order)
303 // Compiling against Standard Libraries property.
315 public static ModuleBuilder ModuleBuilder {
322 // Public Field, used to track which method is the public entry
325 public MethodInfo EntryPoint;
328 // These are used to generate unique names on the structs and fields.
333 // Makes an initialized struct, returns the field builder that
334 // references the data. Thanks go to Sergey Chaban for researching
335 // how to do this. And coming up with a shorter mechanism than I
336 // was able to figure out.
338 // This works but makes an implicit public struct $ArrayType$SIZE and
339 // makes the fields point to it. We could get more control if we did
342 // 1. DefineNestedType on the impl_details_class with our struct.
344 // 2. Define the field on the impl_details_class
346 public FieldBuilder MakeStaticData (byte [] data)
349 int size = data.Length;
351 if (impl_details_class == null)
352 impl_details_class = mb.DefineType (
353 "<PrivateImplementationDetails>", TypeAttributes.NotPublic);
355 fb = impl_details_class.DefineInitializedData (
356 "$$field-" + (field_count++), data,
357 FieldAttributes.Static | FieldAttributes.Assembly);