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

📄 expression.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 5 页
字号:
				// A plus in front of something is just a no-op, so return the child.				//				return Expr;			case Operator.UnaryNegation:				//				// Deals with -literals				// int     operator- (int x)				// long    operator- (long x)				// float   operator- (float f)				// double  operator- (double d)				// decimal operator- (decimal d)				//				Expression expr = null;				//				// transform - - expr into expr				//				if (Expr is Unary){					Unary unary = (Unary) Expr;										if (unary.Oper == Operator.UnaryNegation)						return unary.Expr;				}				//				// perform numeric promotions to int,				// long, double.				//				//				// The following is inneficient, because we call				// ImplicitConversion too many times.				//				// It is also not clear if we should convert to Float				// or Double initially.				//				if (expr_type == TypeManager.uint32_type){					//					// FIXME: handle exception to this rule that					// permits the int value -2147483648 (-2^31) to					// bt wrote as a decimal interger literal					//					type = TypeManager.int64_type;					Expr = Convert.ImplicitConversion (ec, Expr, type, loc);					return this;				}				if (expr_type == TypeManager.uint64_type){					//					// FIXME: Handle exception of `long value'					// -92233720368547758087 (-2^63) to be wrote as					// decimal integer literal.					//					Error23 (expr_type);					return null;				}				if (expr_type == TypeManager.float_type){					type = expr_type;					return this;				}								expr = Convert.ImplicitConversion (ec, Expr, TypeManager.int32_type, loc);				if (expr != null){					Expr = expr;					type = expr.Type;					return this;				} 				expr = Convert.ImplicitConversion (ec, Expr, TypeManager.int64_type, loc);				if (expr != null){					Expr = expr;					type = expr.Type;					return this;				}				expr = Convert.ImplicitConversion (ec, Expr, TypeManager.double_type, loc);				if (expr != null){					Expr = expr;					type = expr.Type;					return this;				}								Error23 (expr_type);				return null;			}			Error (187, "No such operator '" + OperName (Oper) + "' defined for type '" +			       TypeManager.CSharpName (expr_type) + "'");			return null;		}		public override Expression DoResolve (EmitContext ec)		{			if (Oper == Operator.AddressOf) {				Expr = Expr.DoResolveLValue (ec, new EmptyExpression ());				if (Expr == null || Expr.eclass != ExprClass.Variable){					Error (211, "Cannot take the address of the given expression");					return null;				}			}			else				Expr = Expr.Resolve (ec);						if (Expr == null)				return null;			eclass = ExprClass.Value;			return ResolveOperator (ec);		}		public override Expression DoResolveLValue (EmitContext ec, Expression right)		{			if (Oper == Operator.Indirection)				return DoResolve (ec);			return null;		}		public override void Emit (EmitContext ec)		{			ILGenerator ig = ec.ig;						switch (Oper) {			case Operator.UnaryPlus:				throw new Exception ("This should be caught by Resolve");							case Operator.UnaryNegation:				if (ec.CheckState) {					ig.Emit (OpCodes.Ldc_I4_0);					if (type == TypeManager.int64_type)						ig.Emit (OpCodes.Conv_U8);					Expr.Emit (ec);					ig.Emit (OpCodes.Sub_Ovf);				} else {					Expr.Emit (ec);					ig.Emit (OpCodes.Neg);				}								break;							case Operator.LogicalNot:				Expr.Emit (ec);				ig.Emit (OpCodes.Ldc_I4_0);				ig.Emit (OpCodes.Ceq);				break;							case Operator.OnesComplement:				Expr.Emit (ec);				ig.Emit (OpCodes.Not);				break;							case Operator.AddressOf:				((IMemoryLocation)Expr).AddressOf (ec, AddressOp.LoadStore);				break;							default:				throw new Exception ("This should not happen: Operator = "						     + Oper.ToString ());			}		}		public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)		{			if (Oper == Operator.LogicalNot)				Expr.EmitBranchable (ec, target, !onTrue);			else				base.EmitBranchable (ec, target, onTrue);		}		public override string ToString ()		{			return "Unary (" + Oper + ", " + Expr + ")";		}			}	//	// Unary operators are turned into Indirection expressions	// after semantic analysis (this is so we can take the address	// of an indirection).	//	public class Indirection : Expression, IMemoryLocation, IAssignMethod, IVariable {		Expression expr;		LocalTemporary temporary;		bool prepared;				public Indirection (Expression expr, Location l)		{			this.expr = expr;			type = TypeManager.HasElementType (expr.Type) ? TypeManager.GetElementType (expr.Type) : expr.Type;			eclass = ExprClass.Variable;			loc = l;		}				public override void Emit (EmitContext ec)		{			if (!prepared)				expr.Emit (ec);						LoadFromPtr (ec.ig, Type);		}		public void Emit (EmitContext ec, bool leave_copy)		{			Emit (ec);			if (leave_copy) {				ec.ig.Emit (OpCodes.Dup);				temporary = new LocalTemporary (ec, expr.Type);				temporary.Store (ec);			}		}				public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)		{			prepared = prepare_for_load;						expr.Emit (ec);			if (prepare_for_load)				ec.ig.Emit (OpCodes.Dup);						source.Emit (ec);			if (leave_copy) {				ec.ig.Emit (OpCodes.Dup);				temporary = new LocalTemporary (ec, expr.Type);				temporary.Store (ec);			}						StoreFromPtr (ec.ig, type);						if (temporary != null)				temporary.Emit (ec);		}				public void AddressOf (EmitContext ec, AddressOp Mode)		{			expr.Emit (ec);		}		public override Expression DoResolveLValue (EmitContext ec, Expression right_side)		{			return DoResolve (ec);		}		public override Expression DoResolve (EmitContext ec)		{			//			// Born fully resolved			//			return this;		}				public override string ToString ()		{			return "*(" + expr + ")";		}		#region IVariable Members		public VariableInfo VariableInfo {			get {				return null;			}		}		public bool VerifyFixed ()		{			// A pointer-indirection is always fixed.			return true;		}		#endregion	}		/// <summary>	///   Unary Mutator expressions (pre and post ++ and --)	/// </summary>	///	/// <remarks>	///   UnaryMutator implements ++ and -- expressions.   It derives from	///   ExpressionStatement becuase the pre/post increment/decrement	///   operators can be used in a statement context.	///	/// FIXME: Idea, we could split this up in two classes, one simpler	/// for the common case, and one with the extra fields for more complex	/// classes (indexers require temporary access;  overloaded require method)	///	/// </remarks>	public class UnaryMutator : ExpressionStatement {		[Flags]		public enum Mode : byte {			IsIncrement    = 0,			IsDecrement    = 1,			IsPre          = 0,			IsPost         = 2,						PreIncrement   = 0,			PreDecrement   = IsDecrement,			PostIncrement  = IsPost,			PostDecrement  = IsPost | IsDecrement		}				Mode mode;		bool is_expr = false;		bool recurse = false;				Expression expr;		//		// This is expensive for the simplest case.		//		StaticCallExpr method;					public UnaryMutator (Mode m, Expression e, Location l)		{			mode = m;			loc = l;			expr = e;		}		static string OperName (Mode mode)		{			return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ?				"++" : "--";		}				/// <summary>		///   Returns whether an object of type `t' can be incremented		///   or decremented with add/sub (ie, basically whether we can		///   use pre-post incr-decr operations on it, but it is not a		///   System.Decimal, which we require operator overloading to catch)		/// </summary>		static bool IsIncrementableNumber (Type t)		{			return (t == TypeManager.sbyte_type) ||				(t == TypeManager.byte_type) ||				(t == TypeManager.short_type) ||				(t == TypeManager.ushort_type) ||				(t == TypeManager.int32_type) ||				(t == TypeManager.uint32_type) ||				(t == TypeManager.int64_type) ||				(t == TypeManager.uint64_type) ||				(t == TypeManager.char_type) ||				(t.IsSubclassOf (TypeManager.enum_type)) ||				(t == TypeManager.float_type) ||				(t == TypeManager.double_type) ||				(t.IsPointer && t != TypeManager.void_ptr_type);		}		Expression ResolveOperator (EmitContext ec)		{			Type expr_type = expr.Type;			//			// Step 1: Perform Operator Overload location			//			Expression mg;			string op_name;						if (mode == Mode.PreIncrement || mode == Mode.PostIncrement)				op_name = "op_Increment";			else 				op_name = "op_Decrement";			mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);			if (mg != null) {				method = StaticCallExpr.MakeSimpleCall (					ec, (MethodGroupExpr) mg, expr, loc);				type = method.Type;			} else if (!IsIncrementableNumber (expr_type)) {				Error (187, "No such operator '" + OperName (mode) + "' defined for type '" +				       TypeManager.CSharpName (expr_type) + "'");				   return null;			}			//			// The operand of the prefix/postfix increment decrement operators			// should be an expression that is classified as a variable,			// a property access or an indexer access			//			type = expr_type;			if (expr.eclass == ExprClass.Variable){				LocalVariableReference var = expr as LocalVariableReference;				if ((var != null) && var.IsReadOnly) {					Error (1604, "cannot assign to `" + var.Name + "' because it is readonly");					return null;				}			} else if (expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess){				expr = expr.ResolveLValue (ec, this, Location);				if (expr == null)					return null;			} else {				expr.Error_UnexpectedKind (ec, "variable, indexer or property access", loc);				return null;			}			return this;		}		public override Expression DoResolve (EmitContext ec)		{			expr = expr.Resolve (ec);						if (expr == null)				return null;			eclass = ExprClass.Value;			return ResolveOperator (ec);		}		static int PtrTypeSize (Type t)		{			return GetTypeSize (TypeManager.GetElementType (t));		}		//		// Loads the proper "1" into the stack based on the type, then it emits the		// opcode for the operation requested		//		void LoadOneAndEmitOp (EmitContext ec, Type t)		{			//			// Measure if getting the typecode and using that is more/less efficient			// that comparing types.  t.GetTypeCode() is an internal call.			//			ILGenerator ig = ec.ig;						     			if (t == TypeManager.uint64_type || t == TypeManager.int64_type)				LongConstant.EmitLong (ig, 1);			else if (t == TypeManager.double_type)				ig.Emit (OpCodes.Ldc_R8, 1.0);			else if (t == TypeManager.float_type)				ig.Emit (OpCodes.Ldc_R4, 1.0F);			else if (t.IsPointer){				int n = PtrTypeSize (t);								if (n == 0)					ig.Emit (OpCodes.Sizeof, t);				else					IntConstant.EmitInt (ig, n);			} else 				ig.Emit (OpCodes.Ldc_I4_1);			//			// Now emit the operation			//			if (ec.CheckState){				if (t == TypeManager.int32_type ||				    t == TypeManager.int64_type){					if ((mode & Mode.IsDecrement) != 0)						ig.Emit (OpCodes.Sub_Ovf);					else						ig.Emit (OpCodes.Add_Ovf);				} else if (t == TypeManager.uint32_type ||					   t == TypeManager.uint64_type){					if ((mode & Mode.IsDecrement) != 0)						ig.Emit (OpCodes.Sub_Ovf_Un);					else						ig.Emit (OpCodes.Add_Ovf_Un);				} else {					if ((mode & Mode.IsDecrement) != 0)						ig.Emit (OpCodes.Sub_Ovf);					else						ig.Emit (OpCodes.Add_Ovf);				}			} else {				if ((mode & Mode.IsDecrement) != 0)					ig.Emit (OpCodes.Sub);				else					ig.Emit (OpCodes.Add);			}			if (t == TypeManager.sbyte_type){				if (ec.CheckState)					ig.Emit (OpCodes.Conv_Ovf_I1);				else					ig.Emit (OpCodes.Conv_I1);			} else if (t == TypeManager.byte_type){				if (ec.CheckState)					ig.Emit (OpCodes.Conv_Ovf_U1);				else					ig.Emit (OpCodes.Conv_U1);

⌨️ 快捷键说明

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