Преглед на файлове

2001-08-04 Miguel de Icaza <[email protected]>

	* rootcontext.cs:

	* class.cs (Struct::Struct): set the SEALED flags after
	checking the modifiers.
	(TypeContainer::TypeAttr): new property, returns the
	TypeAttributes for a class.

	* cs-parser.jay (type_list): Oops, list production was creating a
	new list of base types.

	* rootcontext.cs (StdLib): New property.
	(GetInterfaceTypeByName): returns an interface by type name, and
	encapsulates error handling here.
	(GetInterfaces): simplified.
	(ResolveTree): Encapsulated all the tree resolution here.
	(CreateClass, GetClassBases, GetInterfaceOrClass): Create class
	types.

	* driver.cs: Add support for --nostdlib, to avoid loading the
	default assemblies.
	(Main): Do not put tree resolution here.

	* rootcontext.cs: Beginning of the class resolution.

svn path=/trunk/mcs/; revision=404
Miguel de Icaza преди 24 години
родител
ревизия
08e726c19d
променени са 6 файла, в които са добавени 405 реда и са изтрити 84 реда
  1. 22 0
      mcs/mcs/ChangeLog
  2. 31 0
      mcs/mcs/class.cs
  3. 4 3
      mcs/mcs/cs-parser.jay
  4. 31 15
      mcs/mcs/driver.cs
  5. 33 0
      mcs/mcs/report.cs
  6. 284 66
      mcs/mcs/rootcontext.cs

+ 22 - 0
mcs/mcs/ChangeLog

@@ -1,5 +1,27 @@
 2001-08-04  Miguel de Icaza  <[email protected]>
 
+	* rootcontext.cs: 
+
+	* class.cs (Struct::Struct): set the SEALED flags after
+	checking the modifiers.
+	(TypeContainer::TypeAttr): new property, returns the
+	TypeAttributes for a class.  
+
+	* cs-parser.jay (type_list): Oops, list production was creating a
+	new list of base types.
+
+	* rootcontext.cs (StdLib): New property.
+	(GetInterfaceTypeByName): returns an interface by type name, and
+	encapsulates error handling here.
+	(GetInterfaces): simplified.
+	(ResolveTree): Encapsulated all the tree resolution here.
+	(CreateClass, GetClassBases, GetInterfaceOrClass): Create class
+	types. 
+	
+	* driver.cs: Add support for --nostdlib, to avoid loading the
+	default assemblies.
+	(Main): Do not put tree resolution here. 
+
 	* rootcontext.cs: Beginning of the class resolution.
 
 2001-08-03  Miguel de Icaza  <[email protected]>

+ 31 - 0
mcs/mcs/class.cs

@@ -15,6 +15,7 @@
 //
 
 using System.Collections;
+using System.Reflection;
 using System;
 
 namespace CIR {
@@ -315,6 +316,34 @@ namespace CIR {
 			return 0;
 		}
 
+		// <summary>
+		//   Returns the TypeAttributes for this TypeContainer
+		// </summary>
+		public TypeAttributes TypeAttr {
+			get {
+				TypeAttributes x = 0;
+
+				//
+				// FIXME: Figure out exactly how private, public and protected
+				// map to the TypeAttribute flags.
+				//
+				// FIXME: Figure out what `new' in the context of a class/struct means.
+				//
+				// FIXME: figure out what `internal' means in the context of class/structs
+				//
+				if ((mod_flags & Modifiers.PRIVATE) == 0)
+					x |= TypeAttributes.Public;
+				
+				if ((mod_flags & Modifiers.ABSTRACT) != 0)
+					x |= TypeAttributes.Abstract;
+				
+				if ((mod_flags & Modifiers.SEALED) != 0)
+					x |= TypeAttributes.Sealed;
+
+				return x;
+			}
+		}
+		
 		public delegate void VisitContainer (TypeContainer container, object cback_data);
 
 		void VisitTypesAt (TypeContainer root, VisitContainer visit, object cback)
@@ -487,6 +516,8 @@ namespace CIR {
 				accmods = Modifiers.PRIVATE;
 			
 			this.mod_flags = Modifiers.Check (AllowedModifiers, mod, accmods);
+
+			this.mod_flags |= Modifiers.SEALED;
 		}
 	}
 

+ 4 - 3
mcs/mcs/cs-parser.jay

@@ -1289,8 +1289,9 @@ type_list
 	  }
 	| type_list COMMA type
 	  {
-		ArrayList types = new ArrayList ();
-		types.Add ($2);
+		ArrayList types = (ArrayList) $1;
+
+		types.Add ($3);
 		$$ = types;
 	  }
 	;
@@ -1985,7 +1986,7 @@ modifier
 
 opt_class_base
 	: /* empty */		{ $$ = null; }
-	| class_base		{ $$ = $1; }
+	| class_base		{ $$ = $1;   }
 	;
 
 class_base

+ 31 - 15
mcs/mcs/driver.cs

@@ -66,11 +66,12 @@ namespace CSC
 		public void Usage ()
 		{
 			Console.WriteLine (
-				"compiler [-v] [-t tree] [-o output] [-L path] [-r reference] sources.cs\n" +
-				"-v  Verbose parsing\n"+
-				"-o  Specifies output file\n" +
-				"-L  Specifies path for loading assemblies\n" +
-				"-r  References an assembly\n");
+				"compiler [options] source-files\n\n" +
+				"-v         Verbose parsing\n"+
+				"-o         Specifies output file\n" +
+				"-L         Specifies path for loading assemblies\n" +
+				"--nostdlib Does not load core libraries\n" +
+				"-r         References an assembly\n");
 			
 		}
 
@@ -166,7 +167,6 @@ namespace CSC
 			//
 			// Setup defaults
 			//
-			references.Add ("mscorlib");
 			link_paths.Add ("file:///C:/WINNT/Microsoft.NET/Framework/v1.0.2914");
 			
 			for (i = 0; i < args.Length; i++){
@@ -209,6 +209,10 @@ namespace CSC
 						continue;
 					}
 
+					if (arg == "--nostdlib"){
+						context.StdLib = false;
+					}
+
 					Usage ();
 					error_count++;
 					return;
@@ -222,11 +226,18 @@ namespace CSC
 
 				errors += parse (context.Tree, arg);
 			}
+
+			//
+			// Load Core Library for default compilation
+			//
+			if (context.StdLib)
+				references.Add ("mscorlib");
+
 			if (errors > 0){
-				error ("// Parsing failed");
+				error ("Parsing failed");
 				return;
 			} else
-				notice ("// Parsing successful");
+				notice ("Parsing successful");
 
 			//
 			// Load assemblies required
@@ -234,7 +245,7 @@ namespace CSC
 			errors += LoadReferences ();
 
 			if (errors > 0){
-				error ("// Could not load one or more assemblies");
+				error ("Could not load one or more assemblies");
 				return;
 			}
 
@@ -243,8 +254,7 @@ namespace CSC
 			// Dumping the parsed tree.
 			//
 			// This code generation interface is only here
-			// for debugging purposes, it will change as we
-			// move to the new tree. 
+			// for debugging the parser. 
 			//
 			if (generator != null){
 				if (output_file == null){
@@ -258,10 +268,10 @@ namespace CSC
 				errors += generator.Dump (context.Tree, output);
 
 				if (errors > 0){
-					error ("// Compilation failed");
+					error ("Compilation failed");
 					return;
 				} else
-					notice ("// Compilation successful");
+					notice ("Compilation successful");
 
 				output.Flush ();
 				output.Close ();
@@ -281,12 +291,18 @@ namespace CSC
 			//
 			// The second pass of the compiler
 			//
-			context.ResolveInterfaceBases ();
-			context.ResolveClassBases ();
+			context.ResolveTree ();
 
+			if (context.Report.Errors > 0){
+				error ("Compilation failed");
+				return;
+			}
+			
 			context.CloseTypes ();
 			
 			context.CodeGen.Save (output_file);
+
+			notice ("Success");
 		}
 
 	}

+ 33 - 0
mcs/mcs/report.cs

@@ -26,6 +26,14 @@ namespace CIR {
 			warnings++;
 		}
 
+		public void Message (Message m)
+		{
+			if (m is Error)
+				Error (m.code, m.text);
+			else
+				Warning (m.code, m.text);
+		}
+			
 		public int Errors {
 			get {
 				return errors;
@@ -38,4 +46,29 @@ namespace CIR {
 			}
 		}
 	}
+
+	public class Message {
+		public int code;
+		public string text;
+		
+		public Message (int code, string text)
+		{
+			this.code = code;
+			this.text = text;
+		}
+	}
+
+	public class Warning : Message {
+		public Warning (int code, string text) : base (code, text)
+		{
+		}
+	}
+
+	public class Error : Message {
+		public Error (int code, string text) : base (code, text)
+		{
+		}
+	}
 }
+
+

+ 284 - 66
mcs/mcs/rootcontext.cs

@@ -11,6 +11,7 @@ using System;
 using System.Collections;
 using System.Reflection;
 using System.Reflection.Emit;
+using System.Diagnostics;
 
 namespace CIR {
 
@@ -31,21 +32,35 @@ namespace CIR {
 		//
 		CilCodeGen cg;
 
+		//
+		// The module builder pointer
+		//
 		ModuleBuilder mb;
 
+		//
+		// Error reporting object
+		// 
 		Report report;
 
+		//
+		// The `System.Object' type, as it is used so often.
+		//
 		Type object_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 ()
 		{
-			object o = null;
-			
 			tree = new Tree ();
 			type_manager = new TypeManager ();
 			report = new Report ();
 
-			object_type = o.GetType ();
+			object_type = System.Type.GetType ("System.Object");
 		}
 
 		public TypeManager TypeManager {
@@ -76,14 +91,67 @@ namespace CIR {
 			}
 		}
 
+		//
+		// 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
-		// Null on error
+		// Or null if it does not implement any interface.
+		//
+		// Sets the error boolean accoringly.
 		//
-		Type [] GetInterfaces (Interface iface, out bool error)
+		Type [] GetInterfaceBases (Interface iface, out bool error)
 		{
 			ArrayList bases = iface.Bases;
-			Hashtable source_ifaces;
 			Type [] tbases;
 			int i;
 
@@ -93,31 +161,16 @@ namespace CIR {
 			
 			tbases = new Type [bases.Count];
 			i = 0;
-			source_ifaces = tree.Interfaces;
 
 			foreach (string name in iface.Bases){
-				Type t = type_manager.LookupType (name);
-				Interface parent;
-				
-				if (t != null){
-					tbases [i++] = t;
-					continue;
-				}
-				parent = (Interface) source_ifaces [name];
-				if (parent == null){
-					error = true;
-					report.Error (246, "Can not find type `"+name+
-						      "' while defining interface `"+iface.Name+"'");
-					return null;
-				}
-				t = CreateInterface (parent);
+				Type t;
+
+				t = GetInterfaceTypeByName (name);
 				if (t == null){
-					report.Error (529,
-						      "Inherited interface `"+name+"' in `"+
-						      iface.Name+"' is recursive");
 					error = true;
 					return null;
 				}
+				
 				tbases [i++] = t;
 			}
 
@@ -128,11 +181,15 @@ namespace CIR {
 		// Creates the Interface @iface using the ModuleBuilder
 		//
 		// TODO:
-		//   Resolve recursively dependencies.
+		//   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.Definition;
+			Type [] ifaces;
+			string name;
 			bool error;
 
 			if (tb != null)
@@ -140,10 +197,12 @@ namespace CIR {
 			
 			if (iface.InTransit)
 				return null;
+			
 			iface.InTransit = true;
 
-			string name = iface.Name;
-			Type [] ifaces = GetInterfaces (iface, out error);
+			name = iface.Name;
+
+			ifaces = GetInterfaceBases (iface, out error);
 
 			if (error)
 				return null;
@@ -156,47 +215,151 @@ namespace CIR {
 					    ifaces);
 			iface.Definition = tb;
 
-			//
-			// if Recursive_Def (child) == false
-			//      error (child.Name recursive def with iface.Name)
-			//
 			type_manager.AddUserType (name, tb);
 
 			iface.InTransit = false;
 			return tb;
 		}
 
-		// <remarks>
-		//   This function is used to resolve the interfaces:
-		//   it creates the Type's as it scans for the user defined
-		//   interfaces.  This is required so we can tell the
-		//   interfaces from classes appart on the class resolution.
-		// </remarks>
-		public void ResolveInterfaceBases ()
+		//
+		// Returns the type for an interface or a class
+		//
+		Type GetInterfaceOrClass (string name)
 		{
-			Hashtable ifaces = tree.Interfaces;
+			Type t = type_manager.LookupType (name);
+			Class parent;
 
-			if (ifaces == null)
-				return;
+			if (t != null)
+				return t;
+
+			parent = (Class) tree.Classes [name];
+			if (parent == null){
+				report.Error (246, "Can not find type `"+name+"'");
+				return null;
+			}
+
+			t = CreateClass ((Class) parent);
+			if (t == null){
+				report.Error (146, "Class definition is circular: `"+name+"'");
+				return null;
+			}
 
-			foreach (DictionaryEntry de in ifaces)
-				CreateInterface ((Interface) de.Value);
+			return t;
 		}
 
-		Type [] GetBases (out Type parent, out bool error)
+		static bool ugliness_shown = false;
+		
+		//
+		// This function computes the Base class and also the
+		// list of interfaces that the class @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 (Class c, out Type parent, out bool error)
 		{
+			ArrayList bases = c.Bases;
+			int count;
+			int start, j, i;
+			
 			error = false;
 			parent = null;
 
-			return null;
+			if (bases == null){
+				if (stdlib)
+					parent = object_type;
+				else if (c.Name != "System.Object")
+					parent = object_type;
+
+				return null;
+			}
+
+			//
+			// Bases should be null if there are no bases at all
+			//
+			count = bases.Count;
+			Debug.Assert (count > 0);
+
+			if (!ugliness_shown){
+				Console.WriteLine ("This is horrid, kill TypeRef and TypeRefManager in type.cs");
+				ugliness_shown = true;
+			}
+
+			string name = ((TypeRef) bases [0]).UnresolvedData.Name;
+			Type first = GetInterfaceOrClass (name);
+
+			if (first == null){
+				Console.WriteLine ("Handle Struct miguel!");
+				return null;
+			}
+			
+			if (first.IsClass){
+				parent = first;
+				start = 1;
+			} else {
+				parent = object_type;
+				start = 0;
+			}
+
+			//
+			// No interfaces
+			//
+			if (count == 1)
+				return null;
+				
+			Type [] ifaces = new Type [count-start];
+			
+			for (i = start, j = 0; i < count; i++, j++){
+				name = ((TypeRef) bases [i]).UnresolvedData.Name;
+				Type t = GetInterfaceOrClass (name);
+
+				if (t == null){
+					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 `"+c.Name+
+						      "': Cannot inherit from sealed class `"+
+						      bases [i]+"'"+detail);
+					error = true;
+					return null;
+				}
+
+				if (t.IsClass) {
+					if (parent != null){
+						report.Error (527, "In Class `"+c.Name+"', type `"+
+							      name+"' is not an interface");
+						error = true;
+						return null;
+					}
+				}
+				
+				ifaces [j] = t;
+			}
+
+			return ifaces;
 		}
-		
+
+		// <remarks>
+		//   Creates the TypeBuilder for the class @c.  
+		// </remarks>
+		//
 		TypeBuilder CreateClass (Class c)
 		{
 			TypeBuilder tb = c.Definition;
 			Type parent;
 			Type [] ifaces;
 			bool error;
+			string name;
 			
 			if (tb != null)
 				return tb;
@@ -205,36 +368,72 @@ namespace CIR {
 				return null;
 			c.InTransit = true;
 
-			string name = c.Name;
+			name = c.Name;
 
-			if (c.Bases != null){
-				ifaces = GetBases (out parent, out error);
-			} else {
-				ifaces = null;
-				parent = object_type;
-			}
+			ifaces = GetClassBases (c, out parent, out error);
+
+			if (error)
+				return null;
 
+			tb = mb.DefineType (name,
+					    c.TypeAttr | TypeAttributes.Class,
+					    parent,
+					    ifaces);
+			c.Definition = tb;
+			type_manager.AddUserType (name, tb);
+			c.InTransit = false;
+			
 			return tb;
 		}
-		       
+
+		TypeBuilder CreateStruct (Struct s)
+		{
+			// FIXME: I should really just reuse the code above.
+			// 
+
+			return null;
+		}
+
 		// <remarks>
-		//   This function resolves the parenthood of the classes
-		//   This should be invoked after the ResolveInterfaceBases,
-		//   as we need to be able to tell the difference between interfaces
-		//   and classes in the list of `bases' that was provided in the source
+		//   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 ResolveClassBases ()
+		public void ResolveTree ()
 		{
-			Hashtable classes = tree.Classes;
+			Hashtable ifaces, classes, structs;
 
-			if (classes == null)
-				return;
+			//
+			// 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);
+			}
 
-			foreach (DictionaryEntry de in classes){
-				CreateClass ((Class) (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)
+					CreateStruct ((Struct) de.Value);
 			}
-		}
 
+			classes = tree.Classes;
+			if (classes != null){
+				foreach (DictionaryEntry de in classes)
+					CreateClass ((Class) de.Value);
+			}
+		}
+			
 		// <summary>
 		//   Closes all open types
 		// </summary>
@@ -251,6 +450,25 @@ namespace CIR {
 				t.CreateType ();
 			}
 		}
+
+		// <summary>
+		//   Compiling against Standard Libraries property.
+		// </summary>
+		public bool StdLib {
+			get {
+				return stdlib;
+			}
+
+			set {
+				stdlib = value;
+			}
+		}
+
+		public Report Report {
+			get {
+				return report;
+			}
+		}
 	}
 }