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;
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);
152 // Closes all open types
156 // We usually use TypeBuilder types. When we are done
157 // creating the type (which will happen after we have added
158 // methods, fields, etc) we need to "Define" them before we
159 // can save the Assembly
161 public void CloseTypes ()
163 TypeContainer root = Tree.Types;
165 ArrayList ifaces = root.Interfaces;
168 foreach (Interface i in ifaces)
171 foreach (TypeContainer tc in root.Types)
174 if (root.Delegates != null)
175 foreach (Delegate d in root.Delegates)
179 // If we have a <PrivateImplementationDetails> class, close it
181 if (impl_details_class != null){
182 impl_details_class.CreateType ();
187 // Public function used to locate types, this can only
188 // be used after the ResolveTree function has been invoked.
190 // Returns: Type or null if they type can not be found.
192 public Type LookupType (TypeContainer tc, string name, bool silent)
196 t = TypeManager.LookupType (MakeFQN (tc.Namespace.Name, name));
200 // It's possible that name already is fully qualified. So we do
201 // a simple direct lookup without adding any namespace names
203 t = TypeManager.LookupType (name);
207 for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
208 ArrayList using_list = ns.UsingTable;
210 if (using_list == null)
213 foreach (string n in using_list){
214 t = TypeManager.LookupType (MakeFQN (n, name));
220 // For the case the type we are looking for is nested within this one.
221 t = TypeManager.LookupType (tc.Name + "." + name);
226 Report.Error (246, "Cannot find type `"+name+"'");
232 // This is the silent version of LookupType, you can use this
233 // to `probe' for a type
235 public Type LookupType (TypeContainer tc, string name)
237 return LookupType (tc, name, true);
240 public bool IsNamespace (string name)
244 if (tree.Namespaces != null){
245 ns = (Namespace) tree.Namespaces [name];
255 // Populates the structs and classes with fields and methods
258 // This is invoked after all interfaces, structs and classes
259 // have been defined through `ResolveTree'
260 public void PopulateTypes ()
262 if (interface_resolve_order != null)
263 foreach (Interface iface in interface_resolve_order)
266 if (type_container_resolve_order != null)
267 foreach (TypeContainer tc in type_container_resolve_order)
270 ArrayList delegates = Tree.Types.Delegates;
271 if (delegates != null)
272 foreach (Delegate d in delegates)
273 d.Populate (Tree.Types);
277 public void EmitCode ()
279 if (type_container_resolve_order != null)
280 foreach (TypeContainer tc in type_container_resolve_order)
286 // Compiling against Standard Libraries property.
298 public ModuleBuilder ModuleBuilder {
305 // Public Field, used to track which method is the public entry
308 public MethodInfo EntryPoint;
311 // These are used to generate unique names on the structs and fields.
316 // Makes an initialized struct, returns the field builder that
317 // references the data. Thanks go to Sergey Chaban for researching
318 // how to do this. And coming up with a shorter mechanism than I
319 // was able to figure out.
321 // This works but makes an implicit public struct $ArrayType$SIZE and
322 // makes the fields point to it. We could get more control if we did
325 // 1. DefineNestedType on the impl_details_class with our struct.
327 // 2. Define the field on the impl_details_class
329 public FieldBuilder MakeStaticData (byte [] data)
332 int size = data.Length;
334 if (impl_details_class == null)
335 impl_details_class = mb.DefineType (
336 "<PrivateImplementationDetails>", TypeAttributes.NotPublic);
338 fb = impl_details_class.DefineInitializedData (
339 "$$field-" + (field_count++), data,
340 FieldAttributes.Static | FieldAttributes.Assembly);