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
36 // The module builder pointer
41 // Whether we are being linked against the standard libraries.
42 // This is only used to tell whether `System.Object' should
43 // have a parent or not.
48 // This keeps track of the order in which classes were defined
49 // so that we can poulate them in that order.
51 // Order is important, because we need to be able to tell by
52 // examining the parent's list of methods which ones are virtual
53 // or abstract as well as the parent names (to implement new,
56 ArrayList type_container_resolve_order;
57 ArrayList interface_resolve_order;
60 // Holds a reference to the Private Implementation Details
63 TypeBuilder impl_details_class;
70 tree = new Tree (this);
71 TypeManager = new TypeManager ();
80 public CodeGen CodeGen {
87 // Temporary hack, we should probably
88 // intialize `cg' rather than depending on
89 // external initialization of it.
92 mb = cg.ModuleBuilder;
97 // The default compiler checked state
99 public bool Checked = false;
101 string MakeFQN (string nsn, string name)
103 string prefix = (nsn == "" ? "" : nsn + ".");
105 return prefix + name;
109 // This function is used to resolve the hierarchy tree.
110 // It processes interfaces, structs and classes in that order.
112 // It creates the TypeBuilder's as it processes the user defined
115 public void ResolveTree ()
118 // Interfaces are processed first, as classes and
119 // structs might inherit from an object or implement
120 // a set of interfaces, we need to be able to tell
121 // them appart by just using the TypeManager.
124 TypeContainer root = Tree.Types;
126 ArrayList ifaces = root.Interfaces;
128 interface_resolve_order = new ArrayList ();
130 foreach (Interface i in ifaces) {
131 Type t = i.DefineInterface (mb);
133 interface_resolve_order.Add (i);
137 type_container_resolve_order = new ArrayList ();
139 foreach (TypeContainer tc in root.Types) {
140 Type t = tc.DefineType (mb);
142 type_container_resolve_order.Add (tc);
145 if (root.Delegates != null)
146 foreach (Delegate d in root.Delegates)
147 d.DefineDelegate (mb);
149 if (root.Enums != null)
150 foreach (Enum e in root.Enums)
156 // Closes all open types
160 // We usually use TypeBuilder types. When we are done
161 // creating the type (which will happen after we have added
162 // methods, fields, etc) we need to "Define" them before we
163 // can save the Assembly
165 public void CloseTypes ()
167 TypeContainer root = Tree.Types;
169 ArrayList ifaces = root.Interfaces;
172 foreach (Interface i in ifaces)
175 foreach (TypeContainer tc in root.Types)
178 if (root.Delegates != null)
179 foreach (Delegate d in root.Delegates)
182 if (root.Enums != null)
183 foreach (Enum en in root.Enums)
188 // If we have a <PrivateImplementationDetails> class, close it
190 if (impl_details_class != null){
191 impl_details_class.CreateType ();
196 // Public function used to locate types, this can only
197 // be used after the ResolveTree function has been invoked.
199 // Returns: Type or null if they type can not be found.
201 public Type LookupType (TypeContainer tc, string name, bool silent)
205 t = TypeManager.LookupType (MakeFQN (tc.Namespace.Name, name));
209 // It's possible that name already is fully qualified. So we do
210 // a simple direct lookup without adding any namespace names
212 t = TypeManager.LookupType (name);
216 for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
217 ArrayList using_list = ns.UsingTable;
219 if (using_list == null)
222 foreach (string n in using_list){
223 t = TypeManager.LookupType (MakeFQN (n, name));
229 // For the case the type we are looking for is nested within this one.
230 t = TypeManager.LookupType (tc.Name + "." + name);
235 Report.Error (246, "Cannot find type `"+name+"'");
241 // This is the silent version of LookupType, you can use this
242 // to `probe' for a type
244 public Type LookupType (TypeContainer tc, string name)
246 return LookupType (tc, name, true);
249 public bool IsNamespace (string name)
253 if (tree.Namespaces != null){
254 ns = (Namespace) tree.Namespaces [name];
264 // Populates the structs and classes with fields and methods
267 // This is invoked after all interfaces, structs and classes
268 // have been defined through `ResolveTree'
269 public void PopulateTypes ()
271 if (interface_resolve_order != null)
272 foreach (Interface iface in interface_resolve_order)
275 if (type_container_resolve_order != null)
276 foreach (TypeContainer tc in type_container_resolve_order)
279 TypeContainer root = Tree.Types;
281 ArrayList delegates = root.Delegates;
282 if (delegates != null)
283 foreach (Delegate d in delegates)
286 ArrayList enums = root.Enums;
288 foreach (Enum en in enums)
293 public void EmitCode ()
295 if (type_container_resolve_order != null)
296 foreach (TypeContainer tc in type_container_resolve_order)
301 // Compiling against Standard Libraries property.
313 public ModuleBuilder ModuleBuilder {
320 // Public Field, used to track which method is the public entry
323 public MethodInfo EntryPoint;
326 // These are used to generate unique names on the structs and fields.
331 // Makes an initialized struct, returns the field builder that
332 // references the data. Thanks go to Sergey Chaban for researching
333 // how to do this. And coming up with a shorter mechanism than I
334 // was able to figure out.
336 // This works but makes an implicit public struct $ArrayType$SIZE and
337 // makes the fields point to it. We could get more control if we did
340 // 1. DefineNestedType on the impl_details_class with our struct.
342 // 2. Define the field on the impl_details_class
344 public FieldBuilder MakeStaticData (byte [] data)
347 int size = data.Length;
349 if (impl_details_class == null)
350 impl_details_class = mb.DefineType (
351 "<PrivateImplementationDetails>", TypeAttributes.NotPublic);
353 fb = impl_details_class.DefineInitializedData (
354 "$$field-" + (field_count++), data,
355 FieldAttributes.Static | FieldAttributes.Assembly);