2001-10-04 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / rootcontext.cs
index 84f20c82543bfaf78fe18fdce33217a616b19676..43a5dec954150ed4f2d084c772033789088244a6 100755 (executable)
@@ -25,51 +25,41 @@ namespace CIR {
                //
                // Contains loaded assemblies and our generated code as we go.
                //
-               TypeManager type_manager;
+               public TypeManager TypeManager;
 
                //
                // The System.Reflection.Emit CodeGenerator
                //
-               CilCodeGen cg;
+               CodeGen cg;
 
                //
                // The module builder pointer
                //
                ModuleBuilder mb;
 
-               //
-               // Error reporting object
-               // 
-               Report report;
-
-               //
-               // The `System.Object' and `System.ValueType' types, as they
-               // are used often
-               //
-               Type object_type;
-               Type value_type;
-
                //
                // Whether we are being linked against the standard libraries.
                // This is only used to tell whether `System.Object' should
                // have a parent or not.
                //
                bool stdlib = true;
+
+               //
+               // This keeps track of the order in which classes were defined
+               // so that we can poulate them in that order.
+               //
+               // Order is important, because we need to be able to tell by
+               // examining the parent's list of methods which ones are virtual
+               // or abstract as well as the parent names (to implement new, 
+               // override).
+               //
+               ArrayList type_container_resolve_order;
+               ArrayList interface_resolve_order;
                
                public RootContext ()
                {
                        tree = new Tree (this);
-                       type_manager = new TypeManager ();
-                       report = new Report ();
-
-                       object_type = System.Type.GetType ("System.Object");
-                       value_type = System.Type.GetType ("System.ValueType");
-               }
-
-               public TypeManager TypeManager {
-                       get {
-                               return type_manager;
-                       }
+                       TypeManager = new TypeManager ();
                }
 
                public Tree Tree {
@@ -78,7 +68,7 @@ namespace CIR {
                        }
                }
 
-               public CilCodeGen CodeGen {
+               public CodeGen CodeGen {
                        get {
                                return cg;
                        }
@@ -102,7 +92,7 @@ namespace CIR {
                Type GetInterfaceTypeByName (string name)
                {
                        Interface parent;
-                       Type t = type_manager.LookupType (name);
+                       Type t = TypeManager.LookupType (name);
 
                        if (t != null) {
 
@@ -118,7 +108,7 @@ namespace CIR {
                                else
                                        cause = "Should not happen.";
 
-                               report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
+                               Report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
                                
                                return null;
                        }
@@ -132,13 +122,13 @@ namespace CIR {
                                else if (tree.Structs [name] != null)
                                        cause = "is a struct";
                                
-                               report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
+                               Report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
                                return null;
                        }
-                       
+
                        t = CreateInterface ((Interface) parent);
                        if (t == null){
-                               report.Error (529,
+                               Report.Error (529,
                                              "Inherited interface `"+name+"' is circular");
                                return null;
                        }
@@ -210,19 +200,20 @@ namespace CIR {
                        if (error)
                                return null;
 
-                       // FIXME: use the actual accesibility here, not
-                       // TypeAttributes.Public.
                        tb = mb.DefineType (name,
                                            TypeAttributes.Interface |
-                                           TypeAttributes.Public |
+                                           iface.InterfaceAttr |
                                            TypeAttributes.Abstract,
                                            null,   // Parent Type
                                            ifaces);
                        iface.TypeBuilder = tb;
 
-                       type_manager.AddUserType (name, tb);
+                       interface_resolve_order.Add (iface);
+                       
+                       TypeManager.AddUserInterface (name, tb, iface);
 
                        iface.InTransit = false;
+
                        return tb;
                }
 
@@ -240,9 +231,8 @@ namespace CIR {
 
                        error = false;
                        name = MakeFQN (ns, name);
-                       Console.WriteLine ("Attempting to locate " + name);
-
-                       t  = type_manager.LookupType (name);
+                       
+                       t  = TypeManager.LookupType (name);
                        if (t != null)
                                return t;
 
@@ -255,7 +245,7 @@ namespace CIR {
                        if (parent != null){
                                t = CreateType (parent, is_class);
                                if (t == null){
-                                       report.Error (146, "Class definition is circular: `"+name+"'");
+                                       Report.Error (146, "Class definition is circular: `"+name+"'");
                                        error = true;
                                        return null;
                                }
@@ -282,19 +272,20 @@ namespace CIR {
                        if (error)
                                return null;
                        
-                       if (t != null)
+                       if (t != null) 
                                return t;
 
                        //
                        // Attempt to lookup the class on any of the `using'
                        // namespaces
                        //
+
                        for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
                                ArrayList using_list = ns.UsingTable;
 
                                if (using_list == null)
                                        continue;
-                               
+
                                foreach (string n in using_list){
                                        t = LookupInterfaceOrClass (n, name, is_class, out error);
                                        if (error)
@@ -305,7 +296,7 @@ namespace CIR {
                                }
                                
                        }
-                       report.Error (246, "Can not find type `"+name+"'");
+                       Report.Error (246, "Can not find type `"+name+"'");
                        return null;
                }
 
@@ -330,14 +321,14 @@ namespace CIR {
                        if (is_class)
                                parent = null;
                        else
-                               parent = value_type;
+                               parent = TypeManager.value_type;
 
                        if (bases == null){
                                if (is_class){
                                        if (stdlib)
-                                               parent = object_type;
+                                               parent = TypeManager.object_type;
                                        else if (tc.Name != "System.Object")
-                                               parent = object_type;
+                                               parent = TypeManager.object_type;
                                } else {
                                        //
                                        // If we are compiling our runtime,
@@ -345,7 +336,7 @@ namespace CIR {
                                        // parent is `System.Object'.
                                        //
                                        if (!stdlib && tc. Name == "System.ValueType")
-                                               parent = object_type;
+                                               parent = TypeManager.object_type;
                                }
 
                                return null;
@@ -370,7 +361,7 @@ namespace CIR {
                                        parent = first;
                                        start = 1;
                                } else {
-                                       parent = object_type;
+                                       parent = TypeManager.object_type;
                                        start = 0;
                                }
                        } else {
@@ -389,7 +380,7 @@ namespace CIR {
                                }
 
                                if (is_class == false && !t.IsInterface){
-                                       report.Error (527, "In Struct `"+tc.Name+"', type `"+
+                                       Report.Error (527, "In Struct `"+tc.Name+"', type `"+
                                                      name+"' is not an interface");
                                        error = true;
                                        return null;
@@ -401,7 +392,7 @@ namespace CIR {
                                        if (t.IsValueType)
                                                detail = " (a class can not inherit from a struct)";
                                                        
-                                       report.Error (509, "class `"+tc.Name+
+                                       Report.Error (509, "class `"+tc.Name+
                                                      "': Cannot inherit from sealed class `"+
                                                      bases [i]+"'"+detail);
                                        error = true;
@@ -410,7 +401,7 @@ namespace CIR {
 
                                if (t.IsClass) {
                                        if (parent != null){
-                                               report.Error (527, "In Class `"+tc.Name+"', type `"+
+                                               Report.Error (527, "In Class `"+tc.Name+"', type `"+
                                                              name+"' is not an interface");
                                                error = true;
                                                return null;
@@ -449,13 +440,15 @@ namespace CIR {
                        if (error)
                                return null;
 
+                       type_container_resolve_order.Add (tc);
+
                        tb = mb.DefineType (name,
                                            tc.TypeAttr | TypeAttributes.Class,
                                            parent,
                                            ifaces);
-
                        tc.TypeBuilder = tb;
-                       type_manager.AddUserType (name, tb);
+
+                       TypeManager.AddUserType (name, tb, tc);
                        tc.InTransit = false;
                        
                        return tb;
@@ -472,6 +465,8 @@ namespace CIR {
                {
                        Hashtable ifaces, classes, structs;
 
+                       type_container_resolve_order = new ArrayList ();
+                       
                        //
                        // Interfaces are processed first, as classes and
                        // structs might inherit from an object or implement
@@ -480,6 +475,8 @@ namespace CIR {
                        //
                        ifaces = tree.Interfaces;
                        if (ifaces != null){
+                               interface_resolve_order = new ArrayList ();
+                               
                                foreach (DictionaryEntry de in ifaces)
                                        CreateInterface ((Interface) de.Value);
                        }
@@ -507,14 +504,19 @@ namespace CIR {
                //
                // <remarks>
                //   We usually use TypeBuilder types.  When we are done
-               //   creating the type (which will happen after we have addded
+               //   creating the type (which will happen after we have added
                //   methods, fields, etc) we need to "Define" them before we
                //   can save the Assembly
                // </remarks>
                public void CloseTypes ()
                {
-                       foreach (TypeBuilder t in type_manager.UserTypes){
-                               t.CreateType ();
+                       foreach (TypeBuilder t in TypeManager.UserTypes){
+                               try {
+                                       t.CreateType ();
+                               } catch (Exception e){
+                                       Console.WriteLine ("Caught Exception while creating type for " + t);
+                                       Console.WriteLine (e);
+                               }
                        }
                }
 
@@ -528,10 +530,17 @@ namespace CIR {
                {
                        Type t;
 
-                       t = type_manager.LookupType (MakeFQN (tc.Namespace.Name, name));
+                       t = TypeManager.LookupType (MakeFQN (tc.Namespace.Name, name));
                        if (t != null)
                                return t;
 
+                       // It's possible that name already is fully qualified. So we do
+                       // a simple direct lookup without adding any namespace names
+
+                       t = TypeManager.LookupType (name); 
+                       if (t != null)
+                               return t;
+                       
                        for (Namespace ns = tc.Namespace; ns != null; ns = ns.Parent){
                                ArrayList using_list = ns.UsingTable;
 
@@ -539,14 +548,14 @@ namespace CIR {
                                        continue;
 
                                foreach (string n in using_list){
-                                       t = type_manager.LookupType (MakeFQN (n, name));
+                                       t = TypeManager.LookupType (MakeFQN (n, name));
                                        if (t != null)
                                                return t;
                                }
                        }
 
                        if (!silent)
-                               report.Error (246, "Can not find type `"+name+"'");
+                               Report.Error (246, "Cannot find type `"+name+"'");
                        
                        return null;
                }
@@ -555,7 +564,21 @@ namespace CIR {
                {
                        return LookupType (tc, name, true);
                }
-               
+
+               public bool IsNamespace (string name)
+               {
+                       Namespace ns;
+
+                       if (tree.Namespaces != null){
+                               ns = (Namespace) tree.Namespaces [name];
+
+                               if (ns != null)
+                                       return true;
+                       }
+
+                       return false;
+               }
+
                // <summary>
                //   Populates the structs and classes with fields and methods
                // </summary>
@@ -564,25 +587,36 @@ namespace CIR {
                // have been defined through `ResolveTree' 
                public void PopulateTypes ()
                {
-                       Hashtable ifaces, classes;
+                       if (interface_resolve_order != null)
+                               foreach (Interface iface in interface_resolve_order)
+                                       iface.Populate ();
+
+                       if (type_container_resolve_order != null)
+                               foreach (TypeContainer tc in type_container_resolve_order)
+                                       tc.Populate ();
+               }
+
+               public void EmitCode ()
+               {
+                       Hashtable classes, structs;
                        
-                       if ((ifaces = tree.Interfaces) != null){
-                               foreach (DictionaryEntry de in ifaces){
-                                       Interface iface = (Interface) de.Value;
+                       if ((classes = tree.Classes) != null){
+                               foreach (DictionaryEntry de in classes){
+                                       TypeContainer tc = (TypeContainer) de.Value;
 
-                                       iface.Populate ();
+                                       tc.Emit ();
                                }
                        }
 
-                       if ((classes = tree.Classes) != null){
-                               foreach (DictionaryEntry de in classes){
+                       if ((structs = tree.Structs) != null){
+                               foreach (DictionaryEntry de in structs){
                                        TypeContainer tc = (TypeContainer) de.Value;
 
-                                       tc.Populate (this);
+                                       tc.Emit ();
                                }
                        }
                }
-
+               
                // <summary>
                //   Compiling against Standard Libraries property.
                // </summary>
@@ -596,11 +630,11 @@ namespace CIR {
                        }
                }
 
-               public Report Report {
-                       get {
-                               return report;
-                       }
-               }
+               //
+               // Public Field, used to track which method is the public entry
+               // point.
+               //
+               public MethodInfo EntryPoint;
        }
 }