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 // FIXME: use the actual accesibility here, not
214 // TypeAttributes.Public.
215 tb = mb.DefineType (name,
216 TypeAttributes.Interface |
217 TypeAttributes.Public |
218 TypeAttributes.Abstract,
221 iface.TypeBuilder = tb;
223 type_manager.AddUserType (name, tb);
225 iface.InTransit = false;
229 string MakeFQN (string nsn, string name)
231 string prefix = (nsn == "" ? "" : nsn + ".");
233 return prefix + name;
236 Type LookupInterfaceOrClass (string ns, string name, bool is_class, out bool error)
238 TypeContainer parent;
242 name = MakeFQN (ns, name);
243 Console.WriteLine ("Attempting to locate " + name);
245 t = type_manager.LookupType (name);
250 parent = (Class) tree.Classes [name];
252 parent = (Struct) tree.Structs [name];
256 t = CreateType (parent, is_class);
258 report.Error (146, "Class definition is circular: `"+name+"'");
270 // returns the type for an interface or a class, this will recursively
271 // try to define the types that it depends on.
273 Type GetInterfaceOrClass (TypeContainer tc, string name, bool is_class)
279 // Attempt to lookup the class on our namespace
281 t = LookupInterfaceOrClass (tc.Namespace.Name, name, is_class, out error);
289 // 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);
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 addded
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 for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
536 ArrayList using_list = ns.UsingTable;
538 if (using_list == null)
541 foreach (string n in using_list){
542 t = type_manager.LookupType (MakeFQN (n, name));
549 report.Error (246, "Can not find type `"+name+"'");
554 public Type LookupType (TypeContainer tc, string name)
556 return LookupType (tc, name, true);
559 public bool IsNamespace (string name)
561 Console.WriteLine ("FIXME: IsNamespace returns false always!");
566 // Populates the structs and classes with fields and methods
569 // This is invoked after all interfaces, structs and classes
570 // have been defined through `ResolveTree'
571 public void PopulateTypes ()
573 Hashtable ifaces, classes;
575 if ((ifaces = tree.Interfaces) != null){
576 foreach (DictionaryEntry de in ifaces){
577 Interface iface = (Interface) de.Value;
583 if ((classes = tree.Classes) != null){
584 foreach (DictionaryEntry de in classes){
585 TypeContainer tc = (TypeContainer) de.Value;
592 public void EmitCode ()
596 if ((classes = tree.Classes) != null){
597 foreach (DictionaryEntry de in classes){
598 TypeContainer tc = (TypeContainer) de.Value;
606 // Compiling against Standard Libraries property.
618 public Report Report {
625 // Public Field, used to track which method is the public entry
628 public MethodInfo EntryPoint;