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

📄 statement.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 5 页
字号:
					throw new Exception ("Variables have not been initialized yet");				return param_map;			}		}		public VariableMap LocalMap {			get {				if ((flags & Flags.VariablesInitialized) == 0)					throw new Exception ("Variables have not been initialized yet");				return local_map;			}		}		/// <summary>		///   Emits the variable declarations and labels.		/// </summary>		/// <remarks>		///   tc: is our typecontainer (to resolve type references)		///   ig: is the code generator:		/// </remarks>		public void ResolveMeta (ToplevelBlock toplevel, EmitContext ec, InternalParameters ip)		{			bool old_unsafe = ec.InUnsafe;			// If some parent block was unsafe, we remain unsafe even if this block			// isn't explicitly marked as such.			ec.InUnsafe |= Unsafe;			//			// Compute the VariableMap's.			//			// Unfortunately, we don't know the type when adding variables with			// AddVariable(), so we need to compute this info here.			//			LocalInfo[] locals;			if (variables != null) {				foreach (LocalInfo li in variables.Values)					li.Resolve (ec);				locals = new LocalInfo [variables.Count];				variables.Values.CopyTo (locals, 0);			} else				locals = new LocalInfo [0];			if (Parent != null)				local_map = new VariableMap (Parent.LocalMap, locals);			else				local_map = new VariableMap (locals);			param_map = new VariableMap (ip);			flags |= Flags.VariablesInitialized;			bool old_check_state = ec.ConstantCheckState;			ec.ConstantCheckState = (flags & Flags.Unchecked) == 0;						//			// Process this block variables			//			if (variables != null){				foreach (DictionaryEntry de in variables){					string name = (string) de.Key;					LocalInfo vi = (LocalInfo) de.Value;										if (vi.VariableType == null)						continue;					Type variable_type = vi.VariableType;					if (variable_type.IsPointer){						//						// Am not really convinced that this test is required (Microsoft does it)						// but the fact is that you would not be able to use the pointer variable						// *anyways*						//						if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (variable_type),                                                                                  vi.Location))							continue;					}					if (constants == null)						continue;					Expression cv = (Expression) constants [name];					if (cv == null)						continue;					// Don't let 'const int Foo = Foo;' succeed.					// Removing the name from 'constants' ensures that we get a LocalVariableReference below,					// which in turn causes the 'must be constant' error to be triggered.					constants.Remove (name);					ec.CurrentBlock = this;					Expression e = cv.Resolve (ec);					if (e == null)						continue;					Constant ce = e as Constant;					if (ce == null){						Const.Error_ExpressionMustBeConstant (vi.Location, name);						continue;					}					e = ce.ToType (variable_type, vi.Location);					if (e == null)						continue;					constants.Add (name, e);				}			}			ec.ConstantCheckState = old_check_state;			//			// Now, handle the children			//			if (children != null){				foreach (Block b in children)					b.ResolveMeta (toplevel, ec, ip);			}			ec.InUnsafe = old_unsafe;		}		//		// Emits the local variable declarations for a block		//		public void EmitMeta (EmitContext ec)		{			ILGenerator ig = ec.ig;						if (variables != null){				bool have_captured_vars = ec.HaveCapturedVariables ();								foreach (DictionaryEntry de in variables){					LocalInfo vi = (LocalInfo) de.Value;					if (have_captured_vars && ec.IsCaptured (vi))						continue;					if (vi.Pinned)						//						// This is needed to compile on both .NET 1.x and .NET 2.x						// the later introduced `DeclareLocal (Type t, bool pinned)'						//						vi.LocalBuilder = TypeManager.DeclareLocalPinned (ig, vi.VariableType);					else if (!vi.IsThis)						vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);				}			}			if (temporary_variables != null) {				AnonymousContainer am = ec.CurrentAnonymousMethod;				TypeBuilder scope = null;				if ((am != null) && am.IsIterator) {					scope = am.Scope.ScopeTypeBuilder;					if (scope == null)						throw new InternalErrorException ();				}				foreach (LocalInfo vi in temporary_variables) {					if (scope != null) {						if (vi.FieldBuilder == null)							vi.FieldBuilder = scope.DefineField (								vi.Name, vi.VariableType, FieldAttributes.Assembly);					} else						vi.LocalBuilder = ig.DeclareLocal (vi.VariableType);				}			}			if (children != null){				foreach (Block b in children)					b.EmitMeta (ec);			}		}		void UsageWarning (FlowBranching.UsageVector vector)		{			string name;			if ((variables != null) && (RootContext.WarningLevel >= 3)) {				foreach (DictionaryEntry de in variables){					LocalInfo vi = (LocalInfo) de.Value;										if (vi.Used)						continue;										name = (string) de.Key;					if (vector.IsAssigned (vi.VariableInfo)){						Report.Warning (219, vi.Location, "The variable `{0}' is assigned but its value is never used", name);					} else {						Report.Warning (168, vi.Location, "The variable `{0}' is declared but never used", name);					}				}			}		}		bool unreachable_shown;		bool unreachable;		private void CheckPossibleMistakenEmptyStatement (Statement s)		{			Statement body;			// Some statements are wrapped by a Block. Since			// others' internal could be changed, here I treat			// them as possibly wrapped by Block equally.			Block b = s as Block;			if (b != null && b.statements.Count == 1)				s = (Statement) b.statements [0];			if (s is Lock)				body = ((Lock) s).Statement;			else if (s is For)				body = ((For) s).Statement;			else if (s is Foreach)				body = ((Foreach) s).Statement;			else if (s is While)				body = ((While) s).Statement;			else if (s is Using)				body = ((Using) s).Statement;			else if (s is Fixed)				body = ((Fixed) s).Statement;			else				return;			if (body == null || body is EmptyStatement)				Report.Warning (642, 3, s.loc, "Possible mistaken empty statement");		}		public override bool Resolve (EmitContext ec)		{			Block prev_block = ec.CurrentBlock;			bool ok = true;			int errors = Report.Errors;			ec.CurrentBlock = this;			ec.StartFlowBranching (this);			Report.Debug (4, "RESOLVE BLOCK", StartLocation, ec.CurrentBranching);			int statement_count = statements.Count;			for (int ix = 0; ix < statement_count; ix++){				Statement s = (Statement) statements [ix];				// Check possible empty statement (CS0642)				if (RootContext.WarningLevel >= 3 &&					ix + 1 < statement_count &&						statements [ix + 1] is Block)					CheckPossibleMistakenEmptyStatement (s);				//				// Warn if we detect unreachable code.				//				if (unreachable) {					if (s is Block)						((Block) s).unreachable = true;					if (!unreachable_shown && (RootContext.WarningLevel >= 2)) {						Report.Warning (							162, s.loc, "Unreachable code detected");						unreachable_shown = true;					}				}				//				// Note that we're not using ResolveUnreachable() for unreachable				// statements here.  ResolveUnreachable() creates a temporary				// flow branching and kills it afterwards.  This leads to problems				// if you have two unreachable statements where the first one				// assigns a variable and the second one tries to access it.				//				if (!s.Resolve (ec)) {					ok = false;					statements [ix] = EmptyStatement.Value;					continue;				}				if (unreachable && !(s is LabeledStatement) && !(s is Block))					statements [ix] = EmptyStatement.Value;				num_statements = ix + 1;				if (s is LabeledStatement)					unreachable = false;				else					unreachable = ec.CurrentBranching.CurrentUsageVector.Reachability.IsUnreachable;			}			Report.Debug (4, "RESOLVE BLOCK DONE", StartLocation,				      ec.CurrentBranching, statement_count, num_statements);			FlowBranching.UsageVector vector = ec.DoEndFlowBranching ();			ec.CurrentBlock = prev_block;			// If we're a non-static `struct' constructor which doesn't have an			// initializer, then we must initialize all of the struct's fields.			if ((flags & Flags.IsToplevel) != 0 && 			    !Toplevel.IsThisAssigned (ec) &&			    vector.Reachability.Throws != FlowBranching.FlowReturns.Always)				ok = false;			if ((labels != null) && (RootContext.WarningLevel >= 2)) {				foreach (LabeledStatement label in labels.Values)					if (!label.HasBeenReferenced)						Report.Warning (164, label.loc,								"This label has not been referenced");			}			Report.Debug (4, "RESOLVE BLOCK DONE #2", StartLocation, vector);			if ((vector.Reachability.Returns == FlowBranching.FlowReturns.Always) ||			    (vector.Reachability.Throws == FlowBranching.FlowReturns.Always) ||			    (vector.Reachability.Reachable == FlowBranching.FlowReturns.Never))				flags |= Flags.HasRet;			if (ok && (errors == Report.Errors)) {				if (RootContext.WarningLevel >= 3)					UsageWarning (vector);			}			return ok;		}		public override bool ResolveUnreachable (EmitContext ec, bool warn)		{			unreachable_shown = true;			unreachable = true;			if (warn && (RootContext.WarningLevel >= 2))				Report.Warning (162, loc, "Unreachable code detected");			ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);			bool ok = Resolve (ec);			ec.KillFlowBranching ();			return ok;		}				protected override void DoEmit (EmitContext ec)		{			for (int ix = 0; ix < num_statements; ix++){				Statement s = (Statement) statements [ix];				// Check whether we are the last statement in a				// top-level block.				if (((Parent == null) || Implicit) && (ix+1 == num_statements) && !(s is Block))					ec.IsLastStatement = true;				else					ec.IsLastStatement = false;				s.Emit (ec);			}		}		public override void Emit (EmitContext ec)		{			Block prev_block = ec.CurrentBlock;			ec.CurrentBlock = this;			bool emit_debug_info = (CodeGen.SymbolWriter != null);			bool is_lexical_block = !Implicit && (Parent != null);			if (emit_debug_info) {				if (is_lexical_block)					ec.BeginScope ();				if (variables != null) {					foreach (DictionaryEntry de in variables) {						string name = (string) de.Key;						LocalInfo vi = (LocalInfo) de.Value;						if (vi.LocalBuilder == null)							continue;						ec.DefineLocalVariable (name, vi.LocalBuilder);					}				}			}			ec.Mark (StartLocation, true);			DoEmit (ec);			ec.Mark (EndLocation, true); 			if (emit_debug_info && is_lexical_block)				ec.EndScope ();			ec.CurrentBlock = prev_block;		}		//		// Returns true if we ar ea child of `b'.		//		public bool IsChildOf (Block b)		{			Block current = this;						do {				if (current.Parent == b)					return true;				current = current.Parent;			} while (current != null);			return false;		}		public override string ToString ()		{			return String.Format ("{0} ({1}:{2})", GetType (),ID, StartLocation);		}	}	//	// A toplevel block contains extra information, the split is done	// only to separate information that would otherwise bloat the more	// lightweight Block.	//	// In particular, this was introduced when the support for Anonymous	// Methods was implemented. 	// 	public class ToplevelBlock : Block {		//		// Pointer to the host of this anonymous method, or null		// if we are the topmost block		//		ToplevelBlock container;		CaptureContext capture_context;		FlowBranching top_level_branching;		Hashtable capture_contexts;		ArrayList children;		public bool HasVarargs {			get { return (flags & Flags.HasVarargs) != 0; }			set { flags |= Flags.HasVarargs; }		}		//		// The parameters for the block.		//		public readonly Parameters Parameters;					public void RegisterCaptureContext (CaptureContext cc)		{			if (capture_contexts == null)				capture_contexts = new Hashtable ();			capture_contexts [cc] = cc;		}		public void CompleteContexts ()		{			if (capture_contexts == null)				return;			foreach (CaptureContext cc in capture_contexts.Keys){				cc.AdjustScopes ();			}		}		public CaptureContext ToplevelBlockCaptureContext {			get { return capture_context; }		}		public ToplevelBlock Container {			get { return container; }		}		protected void AddChild (ToplevelBlock block)		{			if (children == null)				children = new ArrayList ();			children.Add (block);		}		//		// Parent is only used by anonymous blocks to link back to their		// parents		//		public ToplevelBlock (ToplevelBlock container, Parameters parameters, Location start) :			this (container, (Flags) 0, parameters, start)		{		}				public ToplevelBlock (Parameters parameters, Location start) :			this (null, (Flags) 0, parameters, start)		{		}		public ToplevelBlock (Flags flags, Parameters parameters, Location start) :			this (null, flags, parameters, start)		{		}		public ToplevelBlock (ToplevelBlock container, Flags flags, Parameters parameters, Location start) :			base (null, flags | Flags.IsToplevel, start, Location.Null)		{			Parameters = parameters == null ? Parameters.EmptyReadOnlyParameters : parameters;			this.container = container;			if (container != null)				container.AddChild (this);		}		public ToplevelBlock (Location loc) : this (null, (Flags) 0, null, loc)		{		}		public void SetHaveAnonymousMethods (Location loc, AnonymousContainer host)		{			if (capture_context == null)				capture_context = new CaptureContext (this, loc, host);		}		public CaptureContext CaptureContext {			get { return capture_context; }		}		public FlowBranching TopLevelBranching {			get { return top_level_branching; }		}		//		// This is used if anonymous methods are used inside an iterator		// (see 2test-22.cs for an example).		//		// The AnonymousMethod is created while parsing - at a time when we don't		// know yet that we're inside an iterator, so it's `Container' is initially		// null.  Later on, when resolving the iterator, we need to move the		// anonymous method into that iterator.		//		public void ReParent (ToplevelBlock new_parent, AnonymousContainer new_host)		{			foreach (ToplevelBlock block in children) {				if (block.CaptureContext == null)					continue;				block.container = new_parent;				block.CaptureContext.ReParent (new_parent, new_host);			}		}		//		// Returns a `ParameterReference' for the given name, or null if there		// is no such parameter		//		public ParameterReference GetParameterReference (string name, Location loc)		{

⌨️ 快捷键说明

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