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

📄 iterators.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 2 页
字号:
//// iterators.cs: Support for implementing iterators//// Author://   Miguel de Icaza (miguel@ximian.com)//// (C) 2003 Ximian, Inc.//// TODO://    Flow analysis for Yield.//    Emit calls to base object constructor.//// Generics note://    Current should be defined to return T, and IEnumerator.Current returns object//using System;using System.Collections;using System.Reflection;using System.Reflection.Emit;namespace Mono.CSharp {	public interface IIteratorContainer {		//		// Invoked if a yield statement is found in the body		//		void SetYields ();	}		public class Yield : Statement {		Expression expr;		ArrayList finally_blocks;		public Yield (Expression expr, Location l)		{			this.expr = expr;			loc = l;		}		public static bool CheckContext (EmitContext ec, Location loc)		{			if (ec.InFinally) {				Report.Error (1625, loc, "Cannot yield in the body of a " +					      "finally clause");				return false;			} 						if (ec.InUnsafe) {				Report.Error (1629, loc, "Unsafe code may not appear in iterators");				return false;			}			if (ec.InCatch){				Report.Error (1631, loc, "Cannot yield a value in the body of a catch clause");				return false;			}			AnonymousContainer am = ec.CurrentAnonymousMethod;			if ((am != null) && !am.IsIterator){				Report.Error (1621, loc, "The yield statement cannot be used inside anonymous method blocks");				return false;			}			if (ec.CurrentBranching.InTryWithCatch ()) {				Report.Error (1626, loc, "Cannot yield a value in the body of a " +					"try block with a catch clause");				return false;			}			return true;		}				public override bool Resolve (EmitContext ec)		{			expr = expr.Resolve (ec);			if (expr == null)				return false;			if (!CheckContext (ec, loc))				return false;			Iterator iterator = ec.CurrentIterator;			if (expr.Type != iterator.IteratorType){				expr = Convert.ImplicitConversionRequired (					ec, expr, iterator.IteratorType, loc);				if (expr == null)					return false;			}			ec.CurrentBranching.StealFinallyClauses (ref finally_blocks);			return true;		}		protected override void DoEmit (EmitContext ec)		{			ec.CurrentIterator.MarkYield (ec, expr, finally_blocks);		}	}	public class YieldBreak : Statement {		public YieldBreak (Location l)		{			loc = l;		}		public override bool Resolve (EmitContext ec)		{			if (!Yield.CheckContext (ec, loc))				return false;			ec.CurrentBranching.CurrentUsageVector.Goto ();			return true;		}		protected override void DoEmit (EmitContext ec)		{			ec.CurrentIterator.EmitYieldBreak (ec.ig);		}	}	public class Iterator : Class {		protected ToplevelBlock original_block;		protected ToplevelBlock block;		Type iterator_type;		TypeExpr iterator_type_expr;		bool is_enumerable;		public readonly bool IsStatic;		//		// The state as we generate the iterator		//		Label move_next_ok, move_next_error;		ArrayList resume_points = new ArrayList ();		int pc;				//		// Context from the original method		//		TypeContainer container;		Type this_type;		InternalParameters parameters;		IMethodData orig_method;		MoveNextMethod move_next_method;		Constructor ctor;		CaptureContext cc;		protected enum State {			Uninitialized	= -2,			After,			Running		}		static int proxy_count;		public void EmitYieldBreak (ILGenerator ig)		{			ig.Emit (OpCodes.Ldarg_0);			IntConstant.EmitInt (ig, (int) State.After);			ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);			ig.Emit (OpCodes.Br, move_next_error);		}		public void EmitMoveNext (EmitContext ec)		{			ILGenerator ig = ec.ig;			move_next_ok = ig.DefineLabel ();			move_next_error = ig.DefineLabel ();			LocalBuilder retval = ec.GetTemporaryLocal (TypeManager.int32_type);			ig.BeginExceptionBlock ();			Label dispatcher = ig.DefineLabel ();			ig.Emit (OpCodes.Br, dispatcher);			ResumePoint entry_point = new ResumePoint (null);			resume_points.Add (entry_point);			entry_point.Define (ig);			ec.EmitTopBlock (orig_method, original_block, parameters);			EmitYieldBreak (ig);			ig.MarkLabel (dispatcher);			Label [] labels = new Label [resume_points.Count];			for (int i = 0; i < labels.Length; i++)				labels [i] = ((ResumePoint) resume_points [i]).Label;			ig.Emit (OpCodes.Ldarg_0);			ig.Emit (OpCodes.Ldfld, pc_field.FieldBuilder);			ig.Emit (OpCodes.Switch, labels);			Label end = ig.DefineLabel ();			ig.MarkLabel (move_next_error);			ig.Emit (OpCodes.Ldc_I4_0); 			ig.Emit (OpCodes.Stloc, retval);			ig.Emit (OpCodes.Leave, end);			ig.MarkLabel (move_next_ok);			ig.Emit (OpCodes.Ldc_I4_1);			ig.Emit (OpCodes.Stloc, retval);			ig.Emit (OpCodes.Leave, end);			ig.BeginFaultBlock ();			ig.Emit (OpCodes.Ldarg_0);			ig.Emit (OpCodes.Callvirt, dispose.MethodBuilder);			ig.EndExceptionBlock ();			ig.MarkLabel (end);			ig.Emit (OpCodes.Ldloc, retval);			ig.Emit (OpCodes.Ret);		}		public void EmitDispose (EmitContext ec)		{			ILGenerator ig = ec.ig;			Label end = ig.DefineLabel ();			Label dispatcher = ig.DefineLabel ();			ig.Emit (OpCodes.Br, dispatcher);			Label [] labels = new Label [resume_points.Count];			for (int i = 0; i < labels.Length; i++) {				ResumePoint point = (ResumePoint) resume_points [i];				if (point.FinallyBlocks == null) {					labels [i] = end;					continue;				}				labels [i] = ig.DefineLabel ();				ig.MarkLabel (labels [i]);				ig.BeginExceptionBlock ();				ig.BeginFinallyBlock ();				foreach (ExceptionStatement stmt in point.FinallyBlocks) {					if (stmt != null)						stmt.EmitFinally (ec);				}				ig.EndExceptionBlock ();				ig.Emit (OpCodes.Br, end);			}						ig.MarkLabel (dispatcher);			ig.Emit (OpCodes.Ldarg_0);			ig.Emit (OpCodes.Ldfld, pc_field.FieldBuilder);			ig.Emit (OpCodes.Switch, labels);			ig.Emit (OpCodes.Ldarg_0);			IntConstant.EmitInt (ig, (int) State.After);			ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);			ig.MarkLabel (end);		}		protected class ResumePoint		{			public Label Label;			public readonly ExceptionStatement[] FinallyBlocks;			public ResumePoint (ArrayList list)			{				if (list != null) {					FinallyBlocks = new ExceptionStatement [list.Count];					list.CopyTo (FinallyBlocks, 0);				}			}			public void Define (ILGenerator ig)			{				Label = ig.DefineLabel ();				ig.MarkLabel (Label);			}		}		//		// Called back from Yield		//		public void MarkYield (EmitContext ec, Expression expr,				       ArrayList finally_blocks)		{			ILGenerator ig = ec.ig;			// Store the new current			ig.Emit (OpCodes.Ldarg_0);			expr.Emit (ec);			ig.Emit (OpCodes.Stfld, current_field.FieldBuilder);			// increment pc			pc++;			ig.Emit (OpCodes.Ldarg_0);			IntConstant.EmitInt (ig, pc);			ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);			// Return ok			ig.Emit (OpCodes.Br, move_next_ok);			ResumePoint point = new ResumePoint (finally_blocks);			resume_points.Add (point);			point.Define (ig);		}		public void MarkFinally (EmitContext ec, ArrayList finally_blocks)		{			ILGenerator ig = ec.ig;			// increment pc			pc++;			ig.Emit (OpCodes.Ldarg_0);			IntConstant.EmitInt (ig, pc);			ig.Emit (OpCodes.Stfld, pc_field.FieldBuilder);			ResumePoint point = new ResumePoint (finally_blocks);			resume_points.Add (point);			point.Define (ig);		}		private static MemberName MakeProxyName (string name, Location loc)		{			int pos = name.LastIndexOf ('.');			if (pos > 0)				name = name.Substring (pos + 1);			return new MemberName ("<" + name + ">__" + (proxy_count++), loc);		}		//		// Our constructor		//		public Iterator (IMethodData m_container, TypeContainer container,				 InternalParameters parameters,				 int modifiers)			: base (container.NamespaceEntry, container, MakeProxyName (m_container.MethodName.Name, m_container.Location),				(modifiers & Modifiers.UNSAFE) | Modifiers.PRIVATE, null)		{			this.orig_method = m_container;			this.container = container;			this.parameters = parameters;			this.original_block = orig_method.Block;			this.block = new ToplevelBlock (orig_method.Block, parameters.Parameters, orig_method.Location);			IsStatic = (modifiers & Modifiers.STATIC) != 0;		}		public AnonymousContainer Host {			get { return move_next_method; }		}		public bool DefineIterator ()		{			ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);			ec.CurrentAnonymousMethod = move_next_method;			ec.CurrentIterator = this;			ec.InIterator = true;			if (!CheckType ()) {				Report.Error (1624, Location,					"The body of `{0}' cannot be an iterator block because `{1}' is not an iterator interface type",					orig_method.GetSignatureForError (), TypeManager.CSharpName (orig_method.ReturnType));				return false;			}			for (int i = 0; i < parameters.Count; i++){				Parameter.Modifier mod = parameters.ParameterModifier (i);				if ((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) != 0){					Report.Error (						1623, Location,						"Iterators cannot have ref or out parameters");					return false;				}				if ((mod & Parameter.Modifier.ARGLIST) != 0) {					Report.Error (1636, Location, "__arglist is not allowed in parameter list of iterators");					return false;				}				if (parameters.ParameterType (i).IsPointer) {					Report.Error (1637, Location, "Iterators cannot have unsafe parameters or yield types");					return false;				}			}			this_type = container.TypeBuilder;			ArrayList list = new ArrayList ();			if (is_enumerable)				list.Add (new TypeExpression (						  TypeManager.ienumerable_type, Location));			list.Add (new TypeExpression (TypeManager.ienumerator_type, Location));			list.Add (new TypeExpression (TypeManager.idisposable_type, Location));			iterator_type_expr = new TypeExpression (iterator_type, Location);			container.AddIterator (this);			Bases = list;			orig_method.Block = block;			return true;		}		protected override bool DoDefineMembers ()		{			ec.InIterator = true;			ec.CurrentIterator = this;			ec.CurrentAnonymousMethod = move_next_method;			ec.capture_context = cc;			if (!base.DoDefineMembers ())				return false;			return true;		}		public override bool Define ()		{			if (!base.Define ())				return false;			ec.InIterator = true;			ec.CurrentIterator = this;			ec.CurrentAnonymousMethod = move_next_method;			ec.capture_context = cc;			ec.TypeContainer = ec.TypeContainer.Parent;			ec.ContainerType = ec.TypeContainer.TypeBuilder;			ec.ig = move_next_method.method.MethodBuilder.GetILGenerator ();			if (!ctor.Define ())				return false;			bool unreachable;			if (!ec.ResolveTopBlock (null, original_block, parameters, orig_method, out unreachable))				return false;			if (!ec.ResolveTopBlock (null, block, parameters, orig_method, out unreachable))				return false;			original_block.CompleteContexts ();			cc.EmitAnonymousHelperClasses (ec);			return true;		}		//		// Returns the new block for the method, or null on failure		//		protected override bool DefineNestedTypes ()		{			Define_Fields ();			Define_Current ();			Define_MoveNext ();			Define_Reset ();			Define_Dispose ();			Create_Block ();			Define_Constructor ();			if (is_enumerable)				Define_GetEnumerator ();			return base.DefineNestedTypes ();		}		Field pc_field;		Field current_field;		Method dispose;		void Create_Block ()		{			original_block.SetHaveAnonymousMethods (Location, move_next_method);			block.SetHaveAnonymousMethods (Location, move_next_method);			cc = original_block.CaptureContext;			int first = IsStatic ? 0 : 1;			ArrayList args = new ArrayList ();			if (!IsStatic) {				Type t = container.TypeBuilder;				args.Add (new Argument (					new ThisParameterReference (t, Location)));				cc.CaptureThis ();			}			args.Add (new Argument (new BoolLiteral (false, Location)));			for (int i = 0; i < parameters.Count; i++) {				Type t = parameters.ParameterType (i);				string name = parameters.ParameterName (i);				args.Add (new Argument (					new SimpleParameterReference (t, first + i, Location)));				cc.AddParameterToContext (move_next_method, name, t, first + i);			}			Expression new_expr = new New (				new TypeExpression (TypeBuilder, Location), args, Location);			block.AddStatement (new NoCheckReturn (new_expr, Location));		}		void Define_Fields ()		{			pc_field = new Field (				this, TypeManager.system_int32_expr, Modifiers.PRIVATE, "$PC",				null, null, Location);			AddField (pc_field);			current_field = new Field (				this, iterator_type_expr, Modifiers.PRIVATE, "$current",				null, null, Location);			AddField (current_field);		}		void Define_Constructor ()		{			Parameters ctor_params;			ArrayList list = new ArrayList ();

⌨️ 快捷键说明

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