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 TypeManager type_manager;
31 // The System.Reflection.Emit CodeGenerator
36 // The module builder pointer
41 // Error reporting object
46 // The `System.Object' and `System.ValueType' types, as they
53 // Whether we are being linked against the standard libraries.
54 // This is only used to tell whether `System.Object' should
55 // have a parent or not.
61 tree = new Tree (this);
62 type_manager = new TypeManager ();
63 report = new Report ();
65 object_type = System.Type.GetType ("System.Object");
66 value_type = System.Type.GetType ("System.ValueType");
69 public TypeManager TypeManager {
81 public CodeGen CodeGen {
88 // Temporary hack, we should probably
89 // intialize `cg' rather than depending on
90 // external initialization of it.
93 mb = cg.ModuleBuilder;
98 // Returns the Type that represents the interface whose name
102 Type GetInterfaceTypeByName (string name)
105 Type t = type_manager.LookupType (name);
115 cause = "is a struct";
117 cause = "is a class";
119 cause = "Should not happen.";
121 report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
126 parent = (Interface) tree.Interfaces [name];
128 string cause = "is undefined";
130 if (tree.Classes [name] != null)
131 cause = "is a class";
132 else if (tree.Structs [name] != null)
133 cause = "is a struct";
135 report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
139 t = CreateInterface ((Interface) parent);
142 "Inherited interface `"+name+"' is circular");
150 // Returns the list of interfaces that this interface implements
151 // Or null if it does not implement any interface.
153 // Sets the error boolean accoringly.
155 Type [] GetInterfaceBases (Interface iface, out bool error)
157 ArrayList bases = iface.Bases;
165 tbases = new Type [bases.Count];
168 foreach (string name in iface.Bases){
171 t = GetInterfaceTypeByName (name);
184 // Creates the Interface @iface using the ModuleBuilder
187 // Rework the way we recurse, because for recursive
188 // definitions of interfaces (A:B and B:A) we report the
189 // error twice, rather than once.
191 TypeBuilder CreateInterface (Interface iface)
193 TypeBuilder tb = iface.TypeBuilder;
204 iface.InTransit = true;
208 ifaces = GetInterfaceBases (iface, out error);
213 tb = mb.DefineType (name,
214 TypeAttributes.Interface |
215 iface.InterfaceAttr |
216 TypeAttributes.Abstract,
219 iface.TypeBuilder = tb;
221 type_manager.AddUserType (name, tb);
223 iface.InTransit = false;
227 string MakeFQN (string nsn, string name)
229 string prefix = (nsn == "" ? "" : nsn + ".");
231 return prefix + name;
234 Type LookupInterfaceOrClass (string ns, string name, bool is_class, out bool error)
236 TypeContainer parent;
240 name = MakeFQN (ns, name);
241 //Console.WriteLine ("Attempting to locate " + name);
242 report.Error (-200, "Locating :" + name);
244 t = type_manager.LookupType (name);
249 parent = (Class) tree.Classes [name];
251 parent = (Struct) tree.Structs [name];
255 t = CreateType (parent, is_class);
257 report.Error (146, "Class definition is circular: `"+name+"'");
269 // returns the type for an interface or a class, this will recursively
270 // try to define the types that it depends on.
272 Type GetInterfaceOrClass (TypeContainer tc, string name, bool is_class)
278 // Attempt to lookup the class on our namespace
280 t = LookupInterfaceOrClass (tc.Namespace.Name, name, is_class, out error);
288 // Attempt to lookup the class on any of the `using'
292 for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
293 ArrayList using_list = ns.UsingTable;
295 if (using_list == null)
298 foreach (string n in using_list){
299 t = LookupInterfaceOrClass (n, name, is_class, out error);
308 report.Error (246, "Can not find type `"+name+"'");
313 // This function computes the Base class and also the
314 // list of interfaces that the class or struct @c implements.
316 // The return value is an array (might be null) of
317 // interfaces implemented (as Types).
319 // The @parent argument is set to the parent object or null
320 // if this is `System.Object'.
322 Type [] GetClassBases (TypeContainer tc, bool is_class, out Type parent, out bool error)
324 ArrayList bases = tc.Bases;
338 parent = object_type;
339 else if (tc.Name != "System.Object")
340 parent = object_type;
343 // If we are compiling our runtime,
344 // and we are defining ValueType, then our
345 // parent is `System.Object'.
347 if (!stdlib && tc. Name == "System.ValueType")
348 parent = object_type;
355 // Bases should be null if there are no bases at all
358 Debug.Assert (count > 0);
361 string name = (string) bases [0];
362 Type first = GetInterfaceOrClass (tc, name, is_class);
373 parent = object_type;
380 Type [] ifaces = new Type [count-start];
382 for (i = start, j = 0; i < count; i++, j++){
383 string name = (string) bases [i];
384 Type t = GetInterfaceOrClass (tc, name, is_class);
391 if (is_class == false && !t.IsInterface){
392 report.Error (527, "In Struct `"+tc.Name+"', type `"+
393 name+"' is not an interface");
402 detail = " (a class can not inherit from a struct)";
404 report.Error (509, "class `"+tc.Name+
405 "': Cannot inherit from sealed class `"+
406 bases [i]+"'"+detail);
413 report.Error (527, "In Class `"+tc.Name+"', type `"+
414 name+"' is not an interface");
427 // Creates the TypeBuilder for the TypeContainer @tc (a Class or a Struct)
430 TypeBuilder CreateType (TypeContainer tc, bool is_class)
432 TypeBuilder tb = tc.TypeBuilder;
447 ifaces = GetClassBases (tc, is_class, out parent, out error);
452 tb = mb.DefineType (name,
453 tc.TypeAttr | TypeAttributes.Class,
458 type_manager.AddUserType (name, tb, tc);
459 tc.InTransit = false;
465 // This function is used to resolve the hierarchy tree.
466 // It processes interfaces, structs and classes in that order.
468 // It creates the TypeBuilder's as it processes the user defined
471 public void ResolveTree ()
473 Hashtable ifaces, classes, structs;
476 // Interfaces are processed first, as classes and
477 // structs might inherit from an object or implement
478 // a set of interfaces, we need to be able to tell
479 // them appart by just using the TypeManager.
481 ifaces = tree.Interfaces;
483 foreach (DictionaryEntry de in ifaces)
484 CreateInterface ((Interface) de.Value);
488 // Process structs and classes next. Our code assumes
489 // this order (just for error reporting purposes).
491 structs = tree.Structs;
492 if (structs != null){
493 foreach (DictionaryEntry de in structs)
494 CreateType ((Struct) de.Value, false);
497 classes = tree.Classes;
498 if (classes != null){
499 foreach (DictionaryEntry de in classes)
500 CreateType ((Class) de.Value, true);
505 // Closes all open types
509 // We usually use TypeBuilder types. When we are done
510 // creating the type (which will happen after we have added
511 // methods, fields, etc) we need to "Define" them before we
512 // can save the Assembly
514 public void CloseTypes ()
516 foreach (TypeBuilder t in type_manager.UserTypes){
522 // Public function used to locate types, this can only
523 // be used after the ResolveTree function has been invoked.
525 // Returns: Type or null if they type can not be found.
527 public Type LookupType (TypeContainer tc, string name, bool silent)
531 t = type_manager.LookupType (MakeFQN (tc.Namespace.Name, name));
535 // It's possible that name already is fully qualified. So we do
536 // a simple direct lookup without adding any namespace names
538 t = type_manager.LookupType (name);
542 for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
543 ArrayList using_list = ns.UsingTable;
545 if (using_list == null)
548 foreach (string n in using_list){
549 t = type_manager.LookupType (MakeFQN (n, name));
556 report.Error (246, "Cannot find type `"+name+"'");
561 public Type LookupType (TypeContainer tc, string name)
563 return LookupType (tc, name, true);
566 public bool IsNamespace (string name)
570 if (tree.Namespaces){
571 ns = (Namespace) tree.Namespaces [name];
583 // Populates the structs and classes with fields and methods
586 // This is invoked after all interfaces, structs and classes
587 // have been defined through `ResolveTree'
588 public void PopulateTypes ()
590 Hashtable ifaces, classes;
592 if ((ifaces = tree.Interfaces) != null){
593 foreach (DictionaryEntry de in ifaces){
594 Interface iface = (Interface) de.Value;
600 if ((classes = tree.Classes) != null){
601 foreach (DictionaryEntry de in classes){
602 TypeContainer tc = (TypeContainer) de.Value;
609 public void EmitCode ()
613 if ((classes = tree.Classes) != null){
614 foreach (DictionaryEntry de in classes){
615 TypeContainer tc = (TypeContainer) de.Value;
623 // Compiling against Standard Libraries property.
635 public Report Report {
642 // Public Field, used to track which method is the public entry
645 public MethodInfo EntryPoint;