⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ecore.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 5 页
字号:
//// ecore.cs: Core of the Expression representation for the intermediate tree.//// Author://   Miguel de Icaza (miguel@ximian.com)//// (C) 2001, 2002, 2003 Ximian, Inc.////namespace Mono.CSharp {	using System;	using System.Collections;	using System.Diagnostics;	using System.Reflection;	using System.Reflection.Emit;	using System.Text;	/// <remarks>	///   The ExprClass class contains the is used to pass the 	///   classification of an expression (value, variable, namespace,	///   type, method group, property access, event access, indexer access,	///   nothing).	/// </remarks>	public enum ExprClass : byte {		Invalid,				Value,		Variable,		Namespace,		Type,		MethodGroup,		PropertyAccess,		EventAccess,		IndexerAccess,		Nothing, 	}	/// <remarks>	///   This is used to tell Resolve in which types of expressions we're	///   interested.	/// </remarks>	[Flags]	public enum ResolveFlags {		// Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.		VariableOrValue		= 1,		// Returns a type expression.		Type			= 2,		// Returns a method group.		MethodGroup		= 4,		// Mask of all the expression class flags.		MaskExprClass		= 7,		// Disable control flow analysis while resolving the expression.		// This is used when resolving the instance expression of a field expression.		DisableFlowAnalysis	= 8,		// Set if this is resolving the first part of a MemberAccess.		Intermediate		= 16,		// Disable control flow analysis _of struct_ while resolving the expression.		// This is used when resolving the instance expression of a field expression.		DisableStructFlowAnalysis	= 32,	}	//	// This is just as a hint to AddressOf of what will be done with the	// address.	[Flags]	public enum AddressOp {		Store = 1,		Load  = 2,		LoadStore = 3	};		/// <summary>	///   This interface is implemented by variables	/// </summary>	public interface IMemoryLocation {		/// <summary>		///   The AddressOf method should generate code that loads		///   the address of the object and leaves it on the stack.		///		///   The `mode' argument is used to notify the expression		///   of whether this will be used to read from the address or		///   write to the address.		///		///   This is just a hint that can be used to provide good error		///   reporting, and should have no other side effects. 		/// </summary>		void AddressOf (EmitContext ec, AddressOp mode);	}	/// <summary>	///   This interface is implemented by variables	/// </summary>	public interface IVariable {		VariableInfo VariableInfo {			get;		}		bool VerifyFixed ();	}	/// <remarks>	///   Base class for expressions	/// </remarks>	public abstract class Expression {		public ExprClass eclass;		protected Type type;		protected Location loc;				public Type Type {			get { return type; }			set { type = value; }		}		public virtual Location Location {			get { return loc; }		}		/// <summary>		///   Utility wrapper routine for Error, just to beautify the code		/// </summary>		public void Error (int error, string s)		{			if (loc.IsNull)				Report.Error (error, s);			else				Report.Error (error, loc, s);		}		/// <summary>		///   Utility wrapper routine for Warning, just to beautify the code		/// </summary>		public void Warning (int code, string format, params object[] args)		{			Report.Warning (code, loc, format, args);		}		// Not nice but we have broken hierarchy		public virtual void CheckMarshallByRefAccess (Type container) {}		public virtual string GetSignatureForError ()		{			return TypeManager.CSharpName (type);		}		public static bool IsAccessorAccessible (Type invocation_type, MethodInfo mi, out bool must_do_cs1540_check)		{			MethodAttributes ma = mi.Attributes & MethodAttributes.MemberAccessMask;			must_do_cs1540_check = false; // by default we do not check for this			//			// If only accessible to the current class or children			//			if (ma == MethodAttributes.Private)				return invocation_type == mi.DeclaringType ||					TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType);			if (mi.DeclaringType.Assembly == invocation_type.Assembly) {				if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamORAssem)					return true;			} else {				if (ma == MethodAttributes.Assembly || ma == MethodAttributes.FamANDAssem)					return false;			}			// Family and FamANDAssem require that we derive.			// FamORAssem requires that we derive if in different assemblies.			if (ma == MethodAttributes.Family ||			    ma == MethodAttributes.FamANDAssem ||			    ma == MethodAttributes.FamORAssem) {				if (!TypeManager.IsNestedFamilyAccessible (invocation_type, mi.DeclaringType))					return false;				if (!TypeManager.IsNestedChildOf (invocation_type, mi.DeclaringType))					must_do_cs1540_check = true;				return true;			}			return true;		}		/// <summary>		///   Performs semantic analysis on the Expression		/// </summary>		///		/// <remarks>		///   The Resolve method is invoked to perform the semantic analysis		///   on the node.		///		///   The return value is an expression (it can be the		///   same expression in some cases) or a new		///   expression that better represents this node.		///   		///   For example, optimizations of Unary (LiteralInt)		///   would return a new LiteralInt with a negated		///   value.		///   		///   If there is an error during semantic analysis,		///   then an error should be reported (using Report)		///   and a null value should be returned.		///   		///   There are two side effects expected from calling		///   Resolve(): the the field variable "eclass" should		///   be set to any value of the enumeration		///   `ExprClass' and the type variable should be set		///   to a valid type (this is the type of the		///   expression).		/// </remarks>		public abstract Expression DoResolve (EmitContext ec);		public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)		{			return null;		}		//		// This is used if the expression should be resolved as a type or namespace name.		// the default implementation fails.   		//		public virtual FullNamedExpression ResolveAsTypeStep (EmitContext ec,  bool silent)		{			return null;		}		//		// This is used to resolve the expression as a type, a null		// value will be returned if the expression is not a type		// reference		//		public TypeExpr ResolveAsTypeTerminal (EmitContext ec, bool silent)		{			int errors = Report.Errors;			FullNamedExpression fne = ResolveAsTypeStep (ec, silent);			if (fne == null)				return null;			if (fne.eclass != ExprClass.Type) {				if (!silent && errors == Report.Errors)					fne.Error_UnexpectedKind (null, "type", loc);				return null;			}			TypeExpr te = fne as TypeExpr;			if (!te.CheckAccessLevel (ec.DeclSpace)) {				ErrorIsInaccesible (loc, TypeManager.CSharpName (te.Type));				return null;			}			te.loc = loc;			return te;		}		public static void ErrorIsInaccesible (Location loc, string name)		{			Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", name);		}		protected static void Error_CannotAccessProtected (Location loc, MemberInfo m, Type qualifier, Type container)		{			Report.Error (1540, loc, "Cannot access protected member `{0}' via a qualifier of type `{1}';"				+ " the qualifier must be of type `{2}' (or derived from it)", 				TypeManager.GetFullNameSignature (m),				TypeManager.CSharpName (qualifier),				TypeManager.CSharpName (container));		}		public virtual void Error_ValueCannotBeConverted (Location loc, Type target, bool expl)		{			if (Type.Name == target.Name){				Report.ExtraInformation (loc,					String.Format (					"The type {0} has two conflicting definitions, one comes from {1} and the other from {2}",					Type.Name, Type.Assembly.FullName, target.Assembly.FullName));							 			}			if (expl) {				Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",					GetSignatureForError (), TypeManager.CSharpName (target));				return;			}						Expression e = (this is EnumConstant) ? ((EnumConstant)this).Child : this;			bool b = Convert.ExplicitNumericConversion (e, target) != null;			if (b || Convert.ExplicitReferenceConversionExists (Type, target) || Convert.ExplicitUnsafe (e, target) != null) {				Report.Error (266, loc, "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)",					TypeManager.CSharpName (Type), TypeManager.CSharpName (target));				return;			}			if (Type != TypeManager.string_type && this is Constant && !(this is NullCast)) {				Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",					GetSignatureForError (), TypeManager.CSharpName (target));				return;			}			Report.Error (29, loc, "Cannot implicitly convert type {0} to `{1}'",				Type == TypeManager.anonymous_method_type ?				"anonymous method" : "`" + GetSignatureForError () + "'",				TypeManager.CSharpName (target));		}		protected static void Error_TypeDoesNotContainDefinition (Location loc, Type type, string name)		{			Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'",				TypeManager.CSharpName (type), name);		}		ResolveFlags ExprClassToResolveFlags ()		{			switch (eclass) {			case ExprClass.Type:			case ExprClass.Namespace:				return ResolveFlags.Type;			case ExprClass.MethodGroup:				return ResolveFlags.MethodGroup;			case ExprClass.Value:			case ExprClass.Variable:			case ExprClass.PropertyAccess:			case ExprClass.EventAccess:			case ExprClass.IndexerAccess:				return ResolveFlags.VariableOrValue;			default:				throw new Exception ("Expression " + GetType () +						     " ExprClass is Invalid after resolve");			}		}	       		/// <summary>		///   Resolves an expression and performs semantic analysis on it.		/// </summary>		///		/// <remarks>		///   Currently Resolve wraps DoResolve to perform sanity		///   checking and assertion checking on what we expect from Resolve.		/// </remarks>		public Expression Resolve (EmitContext ec, ResolveFlags flags)		{			if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) 				return ResolveAsTypeStep (ec, false);			bool old_do_flow_analysis = ec.DoFlowAnalysis;			bool old_omit_struct_analysis = ec.OmitStructFlowAnalysis;			if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)				ec.DoFlowAnalysis = false;			if ((flags & ResolveFlags.DisableStructFlowAnalysis) != 0)				ec.OmitStructFlowAnalysis = true;			Expression e;			bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate;			if (this is SimpleName)				e = ((SimpleName) this).DoResolve (ec, intermediate);			else 				e = DoResolve (ec);			ec.DoFlowAnalysis = old_do_flow_analysis;			ec.OmitStructFlowAnalysis = old_omit_struct_analysis;			if (e == null)				return null;			if ((flags & e.ExprClassToResolveFlags ()) == 0) {				e.Error_UnexpectedKind (flags, loc);				return null;			}			if (e.type == null && !(e is Namespace)) {				throw new Exception (					"Expression " + e.GetType () +					" did not set its type after Resolve\n" +					"called from: " + this.GetType ());			}			return e;		}		/// <summary>		///   Resolves an expression and performs semantic analysis on it.		/// </summary>		public Expression Resolve (EmitContext ec)		{			Expression e = Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);			if (e != null && e.eclass == ExprClass.MethodGroup && RootContext.Version == LanguageVersion.ISO_1) {				((MethodGroupExpr) e).ReportUsageError ();				return null;			}			return e;		}		public Constant ResolveAsConstant (EmitContext ec, MemberCore mc)		{			Expression e = Resolve (ec);			if (e != null) {				Constant c = e as Constant;				if (c != null)					return c;				EmptyCast empty = e as EmptyCast;				if (empty != null) {					c = empty.Child as Constant;					if (c != null) {						// TODO: not sure about this maybe there is easier way how to use EmptyCast						if (e.Type.IsEnum)							c.Type = e.Type;						return c;					}				}			}			Const.Error_ExpressionMustBeConstant (loc, mc.GetSignatureForError ());			return null;		}		/// <summary>		///   Resolves an expression for LValue assignment		/// </summary>		///		/// <remarks>		///   Currently ResolveLValue wraps DoResolveLValue to perform sanity		///   checking and assertion checking on what we expect from Resolve		/// </remarks>		public Expression ResolveLValue (EmitContext ec, Expression right_side, Location loc)		{			int errors = Report.Errors;			Expression e = DoResolveLValue (ec, right_side);			if (e == null) {				if (errors == Report.Errors)					Report.Error (131, loc, "The left-hand side of an assignment or mutating operation must be a variable, property or indexer");				return null;			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -