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

📄 statement.cs

📁 C#编译器源代码。Micorsoft开放源代码
💻 CS
📖 第 1 页 / 共 5 页
字号:
			}		}		public override string ToString ()		{			return String.Format ("LocalInfo ({0},{1},{2},{3})",					      Name, Type, VariableInfo, Location);		}		public bool Used {			get {				return (flags & Flags.Used) != 0;			}			set {				flags = value ? (flags | Flags.Used) : (unchecked (flags & ~Flags.Used));			}		}		public bool ReadOnly {			get {				return (flags & Flags.ReadOnly) != 0;			}		}		public void SetReadOnlyContext (ReadOnlyContext context)		{			flags |= Flags.ReadOnly;			ro_context = context;		}		public string GetReadOnlyContext ()		{			if (!ReadOnly)				throw new InternalErrorException ("Variable is not readonly");			switch (ro_context) {				case ReadOnlyContext.Fixed:					return "fixed variable";				case ReadOnlyContext.Foreach:					return "foreach iteration variable";				case ReadOnlyContext.Using:					return "using variable";			}			throw new NotImplementedException ();		}		//		// Whether the variable is pinned, if Pinned the variable has been 		// allocated in a pinned slot with DeclareLocal.		//		public bool Pinned {			get {				return (flags & Flags.Pinned) != 0;			}			set {				flags = value ? (flags | Flags.Pinned) : (flags & ~Flags.Pinned);			}		}		public bool IsThis {			get {				return (flags & Flags.IsThis) != 0;			}			set {				flags = value ? (flags | Flags.IsThis) : (flags & ~Flags.IsThis);			}		}	}			/// <summary>	///   Block represents a C# block.	/// </summary>	///	/// <remarks>	///   This class is used in a number of places: either to represent	///   explicit blocks that the programmer places or implicit blocks.	///	///   Implicit blocks are used as labels or to introduce variable	///   declarations.	///	///   Top-level blocks derive from Block, and they are called ToplevelBlock	///   they contain extra information that is not necessary on normal blocks.	/// </remarks>	public class Block : Statement {		public Block    Parent;		public readonly Location  StartLocation;		public Location EndLocation = Location.Null;		public readonly ToplevelBlock Toplevel;		[Flags]		public enum Flags : ushort {			Implicit  = 1,			Unchecked = 2,			BlockUsed = 4,			VariablesInitialized = 8,			HasRet = 16,			IsDestructor = 32,			IsToplevel = 64,			Unsafe = 128,			HasVarargs = 256 // Used in ToplevelBlock		}		protected Flags flags;		public bool Implicit {			get { return (flags & Flags.Implicit) != 0; }		}		public bool Unchecked {			get { return (flags & Flags.Unchecked) != 0; }			set { flags |= Flags.Unchecked; }		}		public bool Unsafe {			get { return (flags & Flags.Unsafe) != 0; }			set { flags |= Flags.Unsafe; }		}		//		// The statements in this block		//		ArrayList statements;		int num_statements;		//		// An array of Blocks.  We keep track of children just		// to generate the local variable declarations.		//		// Statements and child statements are handled through the		// statements.		//		ArrayList children;		//		// Labels.  (label, block) pairs.		//		Hashtable labels;		//		// Keeps track of (name, type) pairs		//		IDictionary variables;		//		// Keeps track of constants		Hashtable constants;		//		// Temporary variables.		//		ArrayList temporary_variables;				//		// If this is a switch section, the enclosing switch block.		//		Block switch_block;		protected static int id;		int this_id;				public Block (Block parent)			: this (parent, (Flags) 0, Location.Null, Location.Null)		{ }		public Block (Block parent, Flags flags)			: this (parent, flags, Location.Null, Location.Null)		{ }		public Block (Block parent, Location start, Location end)			: this (parent, (Flags) 0, start, end)		{ }		public Block (Block parent, Flags flags, Location start, Location end)		{			if (parent != null)				parent.AddChild (this);						this.Parent = parent;			this.flags = flags;			this.StartLocation = start;			this.EndLocation = end;			this.loc = start;			this_id = id++;			statements = new ArrayList ();			if ((flags & Flags.IsToplevel) != 0)				Toplevel = (ToplevelBlock) this;			else				Toplevel = parent.Toplevel;			if (parent != null && Implicit) {				if (parent.known_variables == null)					parent.known_variables = new Hashtable ();				// share with parent				known_variables = parent.known_variables;			}						}		public Block CreateSwitchBlock (Location start)		{			Block new_block = new Block (this, start, start);			new_block.switch_block = this;			return new_block;		}		public int ID {			get { return this_id; }		}		protected IDictionary Variables {			get {				if (variables == null)					variables = new ListDictionary ();				return variables;			}		}		void AddChild (Block b)		{			if (children == null)				children = new ArrayList ();						children.Add (b);		}		public void SetEndLocation (Location loc)		{			EndLocation = loc;		}		/// <summary>		///   Adds a label to the current block. 		/// </summary>		///		/// <returns>		///   false if the name already exists in this block. true		///   otherwise.		/// </returns>		///		public bool AddLabel (string name, LabeledStatement target, Location loc)		{			if (switch_block != null)				return switch_block.AddLabel (name, target, loc);			Block cur = this;			while (cur != null) {				if (cur.DoLookupLabel (name) != null) {					Report.Error (						140, loc, "The label `{0}' is a duplicate",						name);					return false;				}				if (!Implicit)					break;				cur = cur.Parent;			}			while (cur != null) {				if (cur.DoLookupLabel (name) != null) {					Report.Error (						158, loc,						"The label `{0}' shadows another label " +						"by the same name in a contained scope.",						name);					return false;				}				if (children != null) {					foreach (Block b in children) {						LabeledStatement s = b.DoLookupLabel (name);						if (s == null)							continue;						Report.Error (							158, s.loc,							"The label `{0}' shadows another " +							"label by the same name in a " +							"contained scope.",							name);						return false;					}				}				cur = cur.Parent;			}			if (labels == null)				labels = new Hashtable ();			labels.Add (name, target);			return true;		}		public LabeledStatement LookupLabel (string name)		{			LabeledStatement s = DoLookupLabel (name);			if (s != null)				return s;			if (children == null)				return null;			foreach (Block child in children) {				if (!child.Implicit)					continue;				s = child.LookupLabel (name);				if (s != null)					return s;			}			return null;		}		LabeledStatement DoLookupLabel (string name)		{			if (switch_block != null)				return switch_block.LookupLabel (name);			if (labels != null)				if (labels.Contains (name))					return ((LabeledStatement) labels [name]);			return null;		}		Hashtable known_variables;		// <summary>		//   Marks a variable with name @name as being used in this or a child block.		//   If a variable name has been used in a child block, it's illegal to		//   declare a variable with the same name in the current block.		// </summary>		void AddKnownVariable (string name, LocalInfo info)		{			if (known_variables == null)				known_variables = new Hashtable ();			known_variables [name] = info;		}		LocalInfo GetKnownVariableInfo (string name)		{			if (known_variables == null)				return null;			return (LocalInfo) known_variables [name];		}		public bool CheckInvariantMeaningInBlock (string name, Expression e, Location loc)		{			Block b = this;			LocalInfo kvi = b.GetKnownVariableInfo (name);			while (kvi == null) {				while (b.Implicit)					b = b.Parent;				b = b.Parent;				if (b == null)					return true;				kvi = b.GetKnownVariableInfo (name);			}			if (kvi.Block == b)				return true;			// Is kvi.Block nested inside 'b'			if (b.known_variables != kvi.Block.known_variables) {				//				// If a variable by the same name it defined in a nested block of this				// block, we violate the invariant meaning in a block.				//				if (b == this) {					Report.SymbolRelatedToPreviousError (kvi.Location, name);					Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", name);					return false;				}				//				// It's ok if the definition is in a nested subblock of b, but not				// nested inside this block -- a definition in a sibling block				// should not affect us.				//				return true;			}			//			// Block 'b' and kvi.Block are the same textual block.			// However, different variables are extant.			//			// Check if the variable is in scope in both blocks.  We use			// an indirect check that depends on AddVariable doing its			// part in maintaining the invariant-meaning-in-block property.			//			if (e is LocalVariableReference || (e is Constant && b.GetLocalInfo (name) != null))				return true;			//			// Even though we detected the error when the name is used, we			// treat it as if the variable declaration was in error.			//			Report.SymbolRelatedToPreviousError (loc, name);			Error_AlreadyDeclared (kvi.Location, name, "parent or current");			return false;		}		public LocalInfo AddVariable (Expression type, string name, Location l)		{			LocalInfo vi = GetLocalInfo (name);			if (vi != null) {				Report.SymbolRelatedToPreviousError (vi.Location, name);				if (known_variables == vi.Block.known_variables)					Report.Error (128, l,						"A local variable named `{0}' is already defined in this scope", name);				else					Error_AlreadyDeclared (l, name, "parent");				return null;			}			vi = GetKnownVariableInfo (name);			if (vi != null) {				Report.SymbolRelatedToPreviousError (vi.Location, name);				Error_AlreadyDeclared (l, name, "child");				return null;			}			int idx;			Parameter p = Toplevel.Parameters.GetParameterByName (name, out idx);			if (p != null) {				Report.SymbolRelatedToPreviousError (p.Location, name);				Error_AlreadyDeclared (l, name, "method argument");				return null;			}			vi = new LocalInfo (type, name, this, l);			Variables.Add (name, vi);			for (Block b = this; b != null; b = b.Parent)				b.AddKnownVariable (name, vi);			if ((flags & Flags.VariablesInitialized) != 0)				throw new Exception ();			return vi;		}		void Error_AlreadyDeclared (Location loc, string var, string reason)		{			Report.Error (136, loc, "A local variable named `{0}' cannot be declared in this scope because it would give a different meaning to `{0}', " +				"which is already used in a `{1}' scope", var, reason);		}		public bool AddConstant (Expression type, string name, Expression value, Location l)		{			if (AddVariable (type, name, l) == null)				return false;						if (constants == null)				constants = new Hashtable ();			constants.Add (name, value);			// A block is considered used if we perform an initialization in a local declaration, even if it is constant.			Use ();			return true;		}		static int next_temp_id = 0;		public LocalInfo AddTemporaryVariable (TypeExpr te, Location loc)		{			if (temporary_variables == null)				temporary_variables = new ArrayList ();			int id = ++next_temp_id;			string name = "$s_" + id.ToString ();			LocalInfo li = new LocalInfo (te, name, this, loc);			li.CompilerGenerated = true;			temporary_variables.Add (li);			return li;		}		public LocalInfo GetLocalInfo (string name)		{			for (Block b = this; b != null; b = b.Parent) {				if (b.variables != null) {					LocalInfo ret = b.variables [name] as LocalInfo;					if (ret != null)						return ret;				}			}			return null;		}		public Expression GetVariableType (string name)		{			LocalInfo vi = GetLocalInfo (name);			return vi == null ? null : vi.Type;		}		public Expression GetConstantExpression (string name)		{			for (Block b = this; b != null; b = b.Parent) {				if (b.constants != null) {					Expression ret = b.constants [name] as Expression;					if (ret != null)						return ret;				}			}			return null;		}				public void AddStatement (Statement s)		{			statements.Add (s);			flags |= Flags.BlockUsed;		}		public bool Used {			get { return (flags & Flags.BlockUsed) != 0; }		}		public void Use ()		{			flags |= Flags.BlockUsed;		}		public bool HasRet {			get { return (flags & Flags.HasRet) != 0; }		}		public bool IsDestructor {			get { return (flags & Flags.IsDestructor) != 0; }		}		public void SetDestructor ()		{			flags |= Flags.IsDestructor;		}		VariableMap param_map, local_map;		public VariableMap ParameterMap {			get {				if ((flags & Flags.VariablesInitialized) == 0)

⌨️ 快捷键说明

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