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

📄 expression.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 5 页
字号:
				return ">";			case Operator.LessThanOrEqual:				return "<=";			case Operator.GreaterThanOrEqual:				return ">=";			case Operator.Equality:				return "==";			case Operator.Inequality:				return "!=";			case Operator.BitwiseAnd:				return "&";			case Operator.BitwiseOr:				return "|";			case Operator.ExclusiveOr:				return "^";			case Operator.LogicalOr:				return "||";			case Operator.LogicalAnd:				return "&&";			}			return oper.ToString ();		}		public override string ToString ()		{			return "operator " + OperName (oper) + "(" + left.ToString () + ", " +				right.ToString () + ")";		}				Expression ForceConversion (EmitContext ec, Expression expr, Type target_type)		{			if (expr.Type == target_type)				return expr;			return Convert.ImplicitConversion (ec, expr, target_type, loc);		}		public static void Error_OperatorAmbiguous (Location loc, Operator oper, Type l, Type r)		{			Report.Error (				34, loc, "Operator `" + OperName (oper) 				+ "' is ambiguous on operands of type `"				+ TypeManager.CSharpName (l) + "' "				+ "and `" + TypeManager.CSharpName (r)				+ "'");		}		bool IsOfType (EmitContext ec, Type l, Type r, Type t, bool check_user_conversions)		{			if ((l == t) || (r == t))				return true;			if (!check_user_conversions)				return false;			if (Convert.ImplicitUserConversionExists (ec, l, t))				return true;			else if (Convert.ImplicitUserConversionExists (ec, r, t))				return true;			else				return false;		}		//		// Note that handling the case l == Decimal || r == Decimal		// is taken care of by the Step 1 Operator Overload resolution.		//		// If `check_user_conv' is true, we also check whether a user-defined conversion		// exists.  Note that we only need to do this if both arguments are of a user-defined		// type, otherwise ConvertImplict() already finds the user-defined conversion for us,		// so we don't explicitly check for performance reasons. 		//		bool DoNumericPromotions (EmitContext ec, Type l, Type r, Expression lexpr, Expression rexpr, bool check_user_conv)		{			if (IsOfType (ec, l, r, TypeManager.double_type, check_user_conv)){				//				// If either operand is of type double, the other operand is				// conveted to type double.				//				if (r != TypeManager.double_type)					right = Convert.ImplicitConversion (ec, right, TypeManager.double_type, loc);				if (l != TypeManager.double_type)					left = Convert.ImplicitConversion (ec, left, TypeManager.double_type, loc);								type = TypeManager.double_type;			} else if (IsOfType (ec, l, r, TypeManager.float_type, check_user_conv)){				//				// if either operand is of type float, the other operand is				// converted to type float.				//				if (r != TypeManager.double_type)					right = Convert.ImplicitConversion (ec, right, TypeManager.float_type, loc);				if (l != TypeManager.double_type)					left = Convert.ImplicitConversion (ec, left, TypeManager.float_type, loc);				type = TypeManager.float_type;			} else if (IsOfType (ec, l, r, TypeManager.uint64_type, check_user_conv)){				Expression e;				Type other;				//				// If either operand is of type ulong, the other operand is				// converted to type ulong.  or an error ocurrs if the other				// operand is of type sbyte, short, int or long				//				if (l == TypeManager.uint64_type){					if (r != TypeManager.uint64_type){						if (right is IntConstant){							IntConstant ic = (IntConstant) right;														e = Convert.TryImplicitIntConversion (l, ic);							if (e != null)								right = e;						} else if (right is LongConstant){							long ll = ((LongConstant) right).Value;							if (ll >= 0)								right = new ULongConstant ((ulong) ll, right.Location);						} else {							e = Convert.ImplicitNumericConversion (ec, right, l);							if (e != null)								right = e;						}					}					other = right.Type;				} else {					if (left is IntConstant){						e = Convert.TryImplicitIntConversion (r, (IntConstant) left);						if (e != null)							left = e;					} else if (left is LongConstant){						long ll = ((LongConstant) left).Value;												if (ll > 0)							left = new ULongConstant ((ulong) ll, right.Location);					} else {						e = Convert.ImplicitNumericConversion (ec, left, r);						if (e != null)							left = e;					}					other = left.Type;				}				if ((other == TypeManager.sbyte_type) ||				    (other == TypeManager.short_type) ||				    (other == TypeManager.int32_type) ||				    (other == TypeManager.int64_type))					Error_OperatorAmbiguous (loc, oper, l, r);				else {					left = ForceConversion (ec, left, TypeManager.uint64_type);					right = ForceConversion (ec, right, TypeManager.uint64_type);				}				type = TypeManager.uint64_type;			} else if (IsOfType (ec, l, r, TypeManager.int64_type, check_user_conv)){				//				// If either operand is of type long, the other operand is converted				// to type long.				//				if (l != TypeManager.int64_type)					left = Convert.ImplicitConversion (ec, left, TypeManager.int64_type, loc);				if (r != TypeManager.int64_type)					right = Convert.ImplicitConversion (ec, right, TypeManager.int64_type, loc);								type = TypeManager.int64_type;			} else if (IsOfType (ec, l, r, TypeManager.uint32_type, check_user_conv)){				//				// If either operand is of type uint, and the other				// operand is of type sbyte, short or int, othe operands are				// converted to type long (unless we have an int constant).				//				Type other = null;								if (l == TypeManager.uint32_type){					if (right is IntConstant){						IntConstant ic = (IntConstant) right;						int val = ic.Value;												if (val >= 0){							right = new UIntConstant ((uint) val, ic.Location);							type = l;														return true;						}					}					other = r;				} else if (r == TypeManager.uint32_type){					if (left is IntConstant){						IntConstant ic = (IntConstant) left;						int val = ic.Value;												if (val >= 0){							left = new UIntConstant ((uint) val, ic.Location);							type = r;							return true;						}					}										other = l;				}				if ((other == TypeManager.sbyte_type) ||				    (other == TypeManager.short_type) ||				    (other == TypeManager.int32_type)){					left = ForceConversion (ec, left, TypeManager.int64_type);					right = ForceConversion (ec, right, TypeManager.int64_type);					type = TypeManager.int64_type;				} else {					//					// if either operand is of type uint, the other					// operand is converd to type uint					//					left = ForceConversion (ec, left, TypeManager.uint32_type);					right = ForceConversion (ec, right, TypeManager.uint32_type);					type = TypeManager.uint32_type;				} 			} else if (l == TypeManager.decimal_type || r == TypeManager.decimal_type){				if (l != TypeManager.decimal_type)					left = Convert.ImplicitConversion (ec, left, TypeManager.decimal_type, loc);				if (r != TypeManager.decimal_type)					right = Convert.ImplicitConversion (ec, right, TypeManager.decimal_type, loc);				type = TypeManager.decimal_type;			} else {				left = ForceConversion (ec, left, TypeManager.int32_type);				right = ForceConversion (ec, right, TypeManager.int32_type);				bool strConv =					Convert.ImplicitConversionExists (ec, lexpr, TypeManager.string_type) &&					Convert.ImplicitConversionExists (ec, rexpr, TypeManager.string_type);				if (strConv && left != null && right != null)					Error_OperatorAmbiguous (loc, oper, l, r);				type = TypeManager.int32_type;			}			return (left != null) && (right != null);		}		static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)		{			Error_OperatorCannotBeApplied (loc, name, TypeManager.CSharpName (l), TypeManager.CSharpName (r));		}		public static void Error_OperatorCannotBeApplied (Location loc, string name, string left, string right)		{			Report.Error (19, loc, "Operator `{0}' cannot be applied to operands of type `{1}' and `{2}'",				name, left, right);		}				void Error_OperatorCannotBeApplied ()		{			Error_OperatorCannotBeApplied (Location, OperName (oper), left.GetSignatureForError (), right.GetSignatureForError ());		}		static bool is_unsigned (Type t)		{			return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||				t == TypeManager.short_type || t == TypeManager.byte_type);		}		static bool is_user_defined (Type t)		{			if (t.IsSubclassOf (TypeManager.value_type) &&			    (!TypeManager.IsBuiltinType (t) || t == TypeManager.decimal_type))				return true;			else				return false;		}		Expression Make32or64 (EmitContext ec, Expression e)		{			Type t= e.Type;						if (t == TypeManager.int32_type || t == TypeManager.uint32_type ||			    t == TypeManager.int64_type || t == TypeManager.uint64_type)				return e;			Expression ee = Convert.ImplicitConversion (ec, e, TypeManager.int32_type, loc);			if (ee != null)				return ee;			ee = Convert.ImplicitConversion (ec, e, TypeManager.uint32_type, loc);			if (ee != null)				return ee;			ee = Convert.ImplicitConversion (ec, e, TypeManager.int64_type, loc);			if (ee != null)				return ee;			ee = Convert.ImplicitConversion (ec, e, TypeManager.uint64_type, loc);			if (ee != null)				return ee;			return null;		}							Expression CheckShiftArguments (EmitContext ec)		{			Expression e;			e = ForceConversion (ec, right, TypeManager.int32_type);			if (e == null){				Error_OperatorCannotBeApplied ();				return null;			}			right = e;			if (((e = Convert.ImplicitConversion (ec, left, TypeManager.int32_type, loc)) != null) ||			    ((e = Convert.ImplicitConversion (ec, left, TypeManager.uint32_type, loc)) != null) ||			    ((e = Convert.ImplicitConversion (ec, left, TypeManager.int64_type, loc)) != null) ||			    ((e = Convert.ImplicitConversion (ec, left, TypeManager.uint64_type, loc)) != null)){				left = e;				type = e.Type;				if (type == TypeManager.int32_type || type == TypeManager.uint32_type){					right = new Binary (Binary.Operator.BitwiseAnd, right, new IntConstant (31, loc));					right = right.DoResolve (ec);				} else {					right = new Binary (Binary.Operator.BitwiseAnd, right, new IntConstant (63, loc));					right = right.DoResolve (ec);				}				return this;			}			Error_OperatorCannotBeApplied ();			return null;		}		//		// This is used to check if a test 'x == null' can be optimized to a reference equals,		// i.e., not invoke op_Equality.		//		static bool EqualsNullIsReferenceEquals (Type t)		{			return t == TypeManager.object_type || t == TypeManager.string_type ||				t == TypeManager.delegate_type || t.IsSubclassOf (TypeManager.delegate_type);		}		static void Warning_UnintendedReferenceComparison (Location loc, string side, Type type)		{			Report.Warning ((side == "left" ? 252 : 253), 2, loc,				"Possible unintended reference comparison; to get a value comparison, " +				"cast the {0} hand side to type `{1}'.", side, TypeManager.CSharpName (type));		}		Expression ResolveOperator (EmitContext ec)		{			Type l = left.Type;			Type r = right.Type;			if (oper == Operator.Equality || oper == Operator.Inequality){				//				// Optimize out call to op_Equality in a few cases.				//				if ((l == TypeManager.null_type && EqualsNullIsReferenceEquals (r)) ||				    (r == TypeManager.null_type && EqualsNullIsReferenceEquals (l))) {				  					Type = TypeManager.bool_type;										return this;				}				// IntPtr equality				if (l == TypeManager.intptr_type && r == TypeManager.intptr_type) {					Type = TypeManager.bool_type;										return this;				}			}			//			// Do not perform operator overload resolution when both sides are			// built-in types			//			Expression left_operators = null, right_operators = null;			if (!(TypeManager.IsPrimitiveType (l) && TypeManager.IsPrimitiveType (r))){				//				// Step 1: Perform Operator Overload location				//				string op = oper_names [(int) oper];								MethodGroupExpr union;				left_operators = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc);				if (r != l){					right_operators = MemberLookup (						ec, r, op, MemberTypes.Method, AllBindingFlags, loc);					union = Invocation.MakeUnionSet (left_operators, right_operators, loc);				} else					union = (MethodGroupExpr) left_operators;								if (union != null) {					ArrayList args = new ArrayList (2);					args.Add (new Argument (left, Argument.AType.Expression));					args.Add (new Argument (right, Argument.AType.Expression));										MethodBase method = Invocation.OverloadResolve (						ec, union, args, true, Location.Null);					if (method != null) {						MethodInfo mi = (MethodInfo) method;												return new BinaryMethod (mi.ReturnType, method, args);					}				}			}						//			// Step 0: String concatenation (because overloading will get this wrong)			//			if (oper == Operator.Addition){				//				// If any of the arguments is a string, cast to string				//								// Simple constant folding				if (left is StringConstant && right is StringConstant)					return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value, left.Location);								if (l == TypeManager.string_type || r == TypeManager.string_type) {					if (r == TypeManager.void_type || l == TypeManager.void_type) {						Error_OperatorCannotBeApplied ();						return null;					}										// try to fold it in on the left					if (left is StringConcat) {						//						// We have to test here for not-null, since we can be doubly-resolved						// take care of not appending twice						//						if (type == null){							type = TypeManager.string_type;							((StringConcat) left).Append (ec, right);							return left.Resolve (ec);						} else {							return left;						}					}										// Otherwise, start a new concat expression					return new StringConcat (ec, loc, left, right).Resolve (ec);				}				//				// Transform a + ( - b) into a - b				//				if (right is Unary){					Unary right_unary = (Unary) right;					if (right_unary.Oper == Unary.Operator.UnaryNegation){						oper = Operator.Subtraction;						right = right_unary.Expr;						r = right.Type;					}				}			}			if (oper == Operator.Equality || oper == Operator.Inequality){				if (l == TypeManager.bool_type || r == TypeManager.bool_type){					if (r != TypeManager.bool_type || l != TypeManager.bool_type){						Error_OperatorCannotBeApplied ();						return null;					}										type = TypeManager.bool_type;					return this;				}				if (l.IsPointer || r.IsPointer) {					if (l.IsPointer && r.IsPointer) {						type = TypeManager.bool_type;						return this;					}					if (l.IsPointer && r == TypeManager.null_type) {						right = new EmptyCast (NullPointer.Null, l);						type = TypeManager.bool_type;						return this;					}					if (r.IsPointer && l == TypeManager.null_type) {						left = new EmptyCast (NullPointer.Null, r);						type = TypeManager.bool_type;						return this;					}				}				//				// operator != (object a, object b)				// operator == (object a, object b)

⌨️ 快捷键说明

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