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

📄 assign.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 2 页
字号:
			// This is used in an embedded assignment.			// As an example, consider the statement "A = X = Y = Z".			//			if (is_embedded && !(source is Constant)) {				// If this is the innermost assignment (the "Y = Z" in our example),				// create a new temporary local, otherwise inherit that variable				// from our child (the "X = (Y = Z)" inherits the local from the				// "Y = Z" assignment).				if (embedded == null) {					if (this is CompoundAssign)						real_temp = temp = new LocalTemporary (ec, target.Type);					else						real_temp = temp = new LocalTemporary (ec, source.Type);				} else					temp = embedded.temp;				// Set the source to the new temporary variable.				// This means that the following target.ResolveLValue () will tell				// the target to read it's source value from that variable.				source = temp;			}			// If we have an embedded assignment, use the embedded assignment's temporary			// local variable as source.			if (embedded != null)				source = (embedded.temp != null) ? embedded.temp : embedded.source;			target = target.ResolveLValue (ec, source, Location);			if (target == null)				return null;			if (source.Equals (target)) {				Report.Warning (1717, 3, loc, "Assignment made to same variable; did you mean to assign something else?");			}			Type target_type = target.Type;			Type source_type = real_source.Type;			// If we're an embedded assignment, our parent will reuse our source as its			// source, it won't read from our target.			if (is_embedded)				type = source_type;			else				type = target_type;			eclass = ExprClass.Value;			if (target is EventExpr) {				EventInfo ei = ((EventExpr) target).EventInfo;				Expression ml = MemberLookup (					ec, ec.ContainerType, ei.Name,					MemberTypes.Event, AllBindingFlags | BindingFlags.DeclaredOnly, loc);				if (ml == null) {				        //					// If this is the case, then the Event does not belong 					// to this Type and so, according to the spec					// is allowed to only appear on the left hand of					// the += and -= operators					//					// Note that target will not appear as an EventExpr					// in the case it is being referenced within the same type container;					// it will appear as a FieldExpr in that case.					//										if (!(source is BinaryDelegate)) {						error70 (ei, loc);						return null;					} 				}			}						FieldExpr field_exp = target as FieldExpr;			if (field_exp != null && field_exp.DeclaringType.IsValueType && !ec.IsConstructor && !ec.IsFieldInitializer) {				field_exp = field_exp.InstanceExpression as FieldExpr;				if (field_exp != null && field_exp.FieldInfo.IsInitOnly) {					if (field_exp.IsStatic) {						Report.Error (1650, loc, "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)",							field_exp.GetSignatureForError ());					} else {						Report.Error (1648, loc, "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)",							field_exp.GetSignatureForError ());					}					return null;				}			}			if (!(target is IAssignMethod) && (target.eclass != ExprClass.EventAccess)) {				Report.Error (131, loc,					      "Left hand of an assignment must be a variable, " +					      "a property or an indexer");				return null;			}			if ((source.eclass == ExprClass.Type) && (source is TypeExpr)) {				source.Error_UnexpectedKind (ec, "variable or value", loc);				return null;			} else if ((RootContext.Version == LanguageVersion.ISO_1) &&				   (source is MethodGroupExpr)){				((MethodGroupExpr) source).ReportUsageError ();				return null;			}			if (target_type == source_type){				if (source is New && target_type.IsValueType &&				    (target.eclass != ExprClass.IndexerAccess) && (target.eclass != ExprClass.PropertyAccess)){					New n = (New) source;										if (n.SetValueTypeVariable (target))						return n;					else						return null;				}								return this;			}						//			// If this assignment/operator was part of a compound binary			// operator, then we allow an explicit conversion, as detailed			// in the spec. 			//			if (this is CompoundAssign){				CompoundAssign a = (CompoundAssign) this;								Binary b = source as Binary;				if (b != null){					//					// 1. if the source is explicitly convertible to the					//    target_type					//										source = Convert.ExplicitConversion (ec, source, target_type, loc);					if (source == null){						a.original_source.Error_ValueCannotBeConverted (loc, target_type, true);						return null;					}									//					// 2. and the original right side is implicitly convertible to					// the type of target					//					if (Convert.ImplicitStandardConversionExists (ec, a.original_source, target_type))						return this;					//					// In the spec 2.4 they added: or if type of the target is int					// and the operator is a shift operator...					//					if (source_type == TypeManager.int32_type &&					    (b.Oper == Binary.Operator.LeftShift || b.Oper == Binary.Operator.RightShift))						return this;					a.original_source.Error_ValueCannotBeConverted (loc, target_type, false);					return null;				}			}			if (source.eclass == ExprClass.MethodGroup && !TypeManager.IsDelegateType (target_type)) {				Report.Error (428, source.Location, "Cannot convert method group `{0}' to non-delegate type `{1}'. Did you intend to invoke the method?",					((MethodGroupExpr)source).Name, target.GetSignatureForError ());				return null;			}			source = Convert.ImplicitConversionRequired (ec, source, target_type, loc);						if (source == null)				return null;			// If we're an embedded assignment, we need to create a new temporary variable			// for the converted value.  Our parent will use this new variable as its source.			// The same applies when we have an embedded assignment - in this case, we need			// to convert our embedded assignment's temporary local variable to the correct			// type and store it in a new temporary local.			if (is_embedded || embedded != null) {				type = target_type;				temp = new LocalTemporary (ec, type);				must_free_temp = true;			}						return this;		}		Expression EmitEmbedded (EmitContext ec)		{			// Emit an embedded assignment.			if (real_temp != null) {				// If we're the innermost assignment, `real_source' is the right-hand				// expression which gets assigned to all the variables left of it.				// Emit this expression and store its result in real_temp.				real_source.Emit (ec);				real_temp.Store (ec);			}			if (embedded != null)				embedded.EmitEmbedded (ec);			// This happens when we've done a type conversion, in this case source will be			// the expression which does the type conversion from real_temp.			// So emit it and store the result in temp; this is the var which will be read			// by our parent.			if (temp != real_temp) {				source.Emit (ec);				temp.Store (ec);			}			Expression temp_source = (temp != null) ? temp : source;			((IAssignMethod) target).EmitAssign (ec, temp_source, false, false);			return temp_source;		}		void ReleaseEmbedded (EmitContext ec)		{			if (embedded != null)				embedded.ReleaseEmbedded (ec);			if (real_temp != null)				real_temp.Release (ec);			if (must_free_temp)				temp.Release (ec);		}		void Emit (EmitContext ec, bool is_statement)		{			if (target is EventExpr) {				((EventExpr) target).EmitAddOrRemove (ec, source);				return;			}						IAssignMethod am = (IAssignMethod) target;			Expression temp_source;			if (embedded != null) {				temp_source = embedded.EmitEmbedded (ec);				if (temp != null) {					source.Emit (ec);					temp.Store (ec);					temp_source = temp;				}			} else				temp_source = source;			am.EmitAssign (ec, temp_source, !is_statement, this is CompoundAssign);							if (embedded != null) {				if (temp != null)					temp.Release (ec);				embedded.ReleaseEmbedded (ec);			}		}				public override void Emit (EmitContext ec)		{			Emit (ec, false);		}		public override void EmitStatement (EmitContext ec)		{			Emit (ec, true);		}	}		//	// This class is used for compound assignments.  	//	class CompoundAssign : Assign {		Binary.Operator op;		public Expression original_source;				public CompoundAssign (Binary.Operator op, Expression target, Expression source)			: base (target, source, target.Location)		{			original_source = source;			this.op = op;		}		protected CompoundAssign (CompoundAssign embedded, Location l)			: this (embedded.op, embedded.target, embedded.source)		{			this.is_embedded = true;		}		protected override Assign GetEmbeddedAssign (Location loc)		{			return new CompoundAssign (this, loc);		}		public Expression ResolveSource (EmitContext ec)		{			return original_source.Resolve (ec);		}		public override Expression DoResolve (EmitContext ec)		{			original_source = original_source.Resolve (ec);			if (original_source == null)				return null;			target = target.Resolve (ec);			if (target == null)				return null;						//			// Only now we can decouple the original source/target			// into a tree, to guarantee that we do not have side			// effects.			//			source = new Binary (op, target, original_source);			return base.DoResolve (ec);		}	}}

⌨️ 快捷键说明

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