Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mcs/mcs/rootcontext.cs')
-rwxr-xr-xmcs/mcs/rootcontext.cs619
1 files changed, 619 insertions, 0 deletions
diff --git a/mcs/mcs/rootcontext.cs b/mcs/mcs/rootcontext.cs
new file mode 100755
index 00000000000..0fa5a5a4117
--- /dev/null
+++ b/mcs/mcs/rootcontext.cs
@@ -0,0 +1,619 @@
+//
+// rootcontext.cs: keeps track of our tree representation, and assemblies loaded.
+//
+// Author: Miguel de Icaza (miguel@ximian.com)
+//
+// Licensed under the terms of the GNU GPL
+//
+// (C) 2001 Ximian, Inc (http://www.ximian.com)
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+
+namespace CIR {
+
+ public class RootContext {
+
+ //
+ // Contains the parsed tree
+ //
+ Tree tree;
+
+ //
+ // Contains loaded assemblies and our generated code as we go.
+ //
+ TypeManager type_manager;
+
+ //
+ // The System.Reflection.Emit CodeGenerator
+ //
+ 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;
+
+ 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;
+ }
+ }
+
+ public Tree Tree {
+ get {
+ return tree;
+ }
+ }
+
+ public CodeGen CodeGen {
+ get {
+ return cg;
+ }
+
+ set {
+ //
+ // Temporary hack, we should probably
+ // intialize `cg' rather than depending on
+ // external initialization of it.
+ //
+ cg = value;
+ mb = cg.ModuleBuilder;
+ }
+ }
+
+ //
+ // Returns the Type that represents the interface whose name
+ // is `name'.
+ //
+
+ Type GetInterfaceTypeByName (string name)
+ {
+ Interface parent;
+ Type t = type_manager.LookupType (name);
+
+ if (t != null) {
+
+ if (t.IsInterface)
+ return t;
+
+ string cause;
+
+ if (t.IsValueType)
+ cause = "is a struct";
+ else if (t.IsClass)
+ cause = "is a class";
+ else
+ cause = "Should not happen.";
+
+ report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
+
+ return null;
+ }
+
+ parent = (Interface) tree.Interfaces [name];
+ if (parent == null){
+ string cause = "is undefined";
+
+ if (tree.Classes [name] != null)
+ cause = "is a class";
+ else if (tree.Structs [name] != null)
+ cause = "is a struct";
+
+ report.Error (527, "`"+name+"' " + cause + ", need an interface instead");
+ return null;
+ }
+
+ t = CreateInterface ((Interface) parent);
+ if (t == null){
+ report.Error (529,
+ "Inherited interface `"+name+"' is circular");
+ return null;
+ }
+
+ return t;
+ }
+
+ //
+ // Returns the list of interfaces that this interface implements
+ // Or null if it does not implement any interface.
+ //
+ // Sets the error boolean accoringly.
+ //
+ Type [] GetInterfaceBases (Interface iface, out bool error)
+ {
+ ArrayList bases = iface.Bases;
+ Type [] tbases;
+ int i;
+
+ error = false;
+ if (bases == null)
+ return null;
+
+ tbases = new Type [bases.Count];
+ i = 0;
+
+ foreach (string name in iface.Bases){
+ Type t;
+
+ t = GetInterfaceTypeByName (name);
+ if (t == null){
+ error = true;
+ return null;
+ }
+
+ tbases [i++] = t;
+ }
+
+ return tbases;
+ }
+
+ //
+ // Creates the Interface @iface using the ModuleBuilder
+ //
+ // TODO:
+ // Rework the way we recurse, because for recursive
+ // definitions of interfaces (A:B and B:A) we report the
+ // error twice, rather than once.
+ //
+ TypeBuilder CreateInterface (Interface iface)
+ {
+ TypeBuilder tb = iface.TypeBuilder;
+ Type [] ifaces;
+ string name;
+ bool error;
+
+ if (tb != null)
+ return tb;
+
+ if (iface.InTransit)
+ return null;
+
+ iface.InTransit = true;
+
+ name = iface.Name;
+
+ ifaces = GetInterfaceBases (iface, out error);
+
+ if (error)
+ return null;
+
+ // FIXME: use the actual accesibility here, not
+ // TypeAttributes.Public.
+ tb = mb.DefineType (name,
+ TypeAttributes.Interface |
+ TypeAttributes.Public |
+ TypeAttributes.Abstract,
+ null, // Parent Type
+ ifaces);
+ iface.TypeBuilder = tb;
+
+ type_manager.AddUserType (name, tb);
+
+ iface.InTransit = false;
+ return tb;
+ }
+
+ string MakeFQN (string nsn, string name)
+ {
+ string prefix = (nsn == "" ? "" : nsn + ".");
+
+ return prefix + name;
+ }
+
+ Type LookupInterfaceOrClass (string ns, string name, bool is_class, out bool error)
+ {
+ TypeContainer parent;
+ Type t;
+
+ error = false;
+ name = MakeFQN (ns, name);
+ Console.WriteLine ("Attempting to locate " + name);
+
+ t = type_manager.LookupType (name);
+ if (t != null)
+ return t;
+
+ if (is_class){
+ parent = (Class) tree.Classes [name];
+ } else {
+ parent = (Struct) tree.Structs [name];
+ }
+
+ if (parent != null){
+ t = CreateType (parent, is_class);
+ if (t == null){
+ report.Error (146, "Class definition is circular: `"+name+"'");
+ error = true;
+ return null;
+ }
+
+ return t;
+ }
+
+ return null;
+ }
+
+ //
+ // returns the type for an interface or a class, this will recursively
+ // try to define the types that it depends on.
+ //
+ Type GetInterfaceOrClass (TypeContainer tc, string name, bool is_class)
+ {
+ Type t;
+ bool error;
+
+ //
+ // Attempt to lookup the class on our namespace
+ //
+ t = LookupInterfaceOrClass (tc.Namespace.Name, name, is_class, out error);
+ if (error)
+ return 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)
+ return null;
+
+ if (t != null)
+ return t;
+ }
+
+ }
+ report.Error (246, "Can not find type `"+name+"'");
+ return null;
+ }
+
+ //
+ // This function computes the Base class and also the
+ // list of interfaces that the class or struct @c implements.
+ //
+ // The return value is an array (might be null) of
+ // interfaces implemented (as Types).
+ //
+ // The @parent argument is set to the parent object or null
+ // if this is `System.Object'.
+ //
+ Type [] GetClassBases (TypeContainer tc, bool is_class, out Type parent, out bool error)
+ {
+ ArrayList bases = tc.Bases;
+ int count;
+ int start, j, i;
+
+ error = false;
+
+ if (is_class)
+ parent = null;
+ else
+ parent = value_type;
+
+ if (bases == null){
+ if (is_class){
+ if (stdlib)
+ parent = object_type;
+ else if (tc.Name != "System.Object")
+ parent = object_type;
+ } else {
+ //
+ // If we are compiling our runtime,
+ // and we are defining ValueType, then our
+ // parent is `System.Object'.
+ //
+ if (!stdlib && tc. Name == "System.ValueType")
+ parent = object_type;
+ }
+
+ return null;
+ }
+
+ //
+ // Bases should be null if there are no bases at all
+ //
+ count = bases.Count;
+ Debug.Assert (count > 0);
+
+ if (is_class){
+ string name = (string) bases [0];
+ Type first = GetInterfaceOrClass (tc, name, is_class);
+
+ if (first == null){
+ error = true;
+ return null;
+ }
+
+ if (first.IsClass){
+ parent = first;
+ start = 1;
+ } else {
+ parent = object_type;
+ start = 0;
+ }
+ } else {
+ start = 0;
+ }
+
+ Type [] ifaces = new Type [count-start];
+
+ for (i = start, j = 0; i < count; i++, j++){
+ string name = (string) bases [i];
+ Type t = GetInterfaceOrClass (tc, name, is_class);
+
+ if (t == null){
+ error = true;
+ return null;
+ }
+
+ if (is_class == false && !t.IsInterface){
+ report.Error (527, "In Struct `"+tc.Name+"', type `"+
+ name+"' is not an interface");
+ error = true;
+ return null;
+ }
+
+ if (t.IsSealed) {
+ string detail = "";
+
+ if (t.IsValueType)
+ detail = " (a class can not inherit from a struct)";
+
+ report.Error (509, "class `"+tc.Name+
+ "': Cannot inherit from sealed class `"+
+ bases [i]+"'"+detail);
+ error = true;
+ return null;
+ }
+
+ if (t.IsClass) {
+ if (parent != null){
+ report.Error (527, "In Class `"+tc.Name+"', type `"+
+ name+"' is not an interface");
+ error = true;
+ return null;
+ }
+ }
+
+ ifaces [j] = t;
+ }
+
+ return ifaces;
+ }
+
+ // <remarks>
+ // Creates the TypeBuilder for the TypeContainer @tc (a Class or a Struct)
+ // </remarks>
+ //
+ TypeBuilder CreateType (TypeContainer tc, bool is_class)
+ {
+ TypeBuilder tb = tc.TypeBuilder;
+ Type parent;
+ Type [] ifaces;
+ bool error;
+ string name;
+
+ if (tb != null)
+ return tb;
+
+ if (tc.InTransit)
+ return null;
+ tc.InTransit = true;
+
+ name = tc.Name;
+
+ ifaces = GetClassBases (tc, is_class, out parent, out error);
+
+ if (error)
+ return null;
+
+ tb = mb.DefineType (name,
+ tc.TypeAttr | TypeAttributes.Class,
+ parent,
+ ifaces);
+
+ tc.TypeBuilder = tb;
+ type_manager.AddUserType (name, tb);
+ tc.InTransit = false;
+
+ return tb;
+ }
+
+ // <remarks>
+ // This function is used to resolve the hierarchy tree.
+ // It processes interfaces, structs and classes in that order.
+ //
+ // It creates the TypeBuilder's as it processes the user defined
+ // types.
+ // </remarks>
+ public void ResolveTree ()
+ {
+ Hashtable ifaces, classes, structs;
+
+ //
+ // Interfaces are processed first, as classes and
+ // structs might inherit from an object or implement
+ // a set of interfaces, we need to be able to tell
+ // them appart by just using the TypeManager.
+ //
+ ifaces = tree.Interfaces;
+ if (ifaces != null){
+ foreach (DictionaryEntry de in ifaces)
+ CreateInterface ((Interface) de.Value);
+ }
+
+ //
+ // Process structs and classes next. Our code assumes
+ // this order (just for error reporting purposes).
+ //
+ structs = tree.Structs;
+ if (structs != null){
+ foreach (DictionaryEntry de in structs)
+ CreateType ((Struct) de.Value, false);
+ }
+
+ classes = tree.Classes;
+ if (classes != null){
+ foreach (DictionaryEntry de in classes)
+ CreateType ((Class) de.Value, true);
+ }
+ }
+
+ // <summary>
+ // Closes all open types
+ // </summary>
+ //
+ // <remarks>
+ // We usually use TypeBuilder types. When we are done
+ // creating the type (which will happen after we have addded
+ // 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 ();
+ }
+ }
+
+ //
+ // Public function used to locate types, this can only
+ // be used after the ResolveTree function has been invoked.
+ //
+ // Returns: Type or null if they type can not be found.
+ //
+ public Type LookupType (TypeContainer tc, string name, bool silent)
+ {
+ Type t;
+
+ t = type_manager.LookupType (MakeFQN (tc.Namespace.Name, name));
+ if (t != null)
+ return t;
+
+ 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 = type_manager.LookupType (MakeFQN (n, name));
+ if (t != null)
+ return t;
+ }
+ }
+
+ if (!silent)
+ report.Error (246, "Can not find type `"+name+"'");
+
+ return null;
+ }
+
+ public Type LookupType (TypeContainer tc, string name)
+ {
+ return LookupType (tc, name, true);
+ }
+
+ // <summary>
+ // Populates the structs and classes with fields and methods
+ // </summary>
+ //
+ // This is invoked after all interfaces, structs and classes
+ // have been defined through `ResolveTree'
+ public void PopulateTypes ()
+ {
+ Hashtable ifaces, classes;
+
+ if ((ifaces = tree.Interfaces) != null){
+ foreach (DictionaryEntry de in ifaces){
+ Interface iface = (Interface) de.Value;
+
+ iface.Populate ();
+ }
+ }
+
+ if ((classes = tree.Classes) != null){
+ foreach (DictionaryEntry de in classes){
+ TypeContainer tc = (TypeContainer) de.Value;
+
+ tc.Populate ();
+ }
+ }
+ }
+
+ public void EmitCode ()
+ {
+ Hashtable classes;
+
+ if ((classes = tree.Classes) != null){
+ foreach (DictionaryEntry de in classes){
+ TypeContainer tc = (TypeContainer) de.Value;
+
+ tc.Emit ();
+ }
+ }
+ }
+
+ // <summary>
+ // Compiling against Standard Libraries property.
+ // </summary>
+ public bool StdLib {
+ get {
+ return stdlib;
+ }
+
+ set {
+ stdlib = value;
+ }
+ }
+
+ public Report Report {
+ get {
+ return report;
+ }
+ }
+ }
+}
+