public override void VisitExpressionStatement(ExpressionStatement node)
		{
			VariableReference theVariableReference = null;
			if (node.Expression.CodeNodeType == CodeNodeType.BinaryExpression &&
				(node.Expression as BinaryExpression).IsAssignmentExpression)
			{
				Expression left = (node.Expression as BinaryExpression).Left;
				if (left.CodeNodeType == CodeNodeType.VariableReferenceExpression)
				{
					theVariableReference = (left as VariableReferenceExpression).Variable;
				}
				else if (left.CodeNodeType == CodeNodeType.VariableDeclarationExpression)
				{
					theVariableReference = (left as VariableDeclarationExpression).Variable;
				}
			}
			if (theVariableReference != null && node.Parent.CodeNodeType == CodeNodeType.BlockStatement && !bannedVariables.Contains(theVariableReference))
			{
				if (!referenceToDeclarationStatementMap.Remove(theVariableReference))
				{
					referenceToDeclarationStatementMap[theVariableReference] = node;
				}
				else
				{
					bannedVariables.Add(theVariableReference);
				}
				base.Visit((node.Expression as BinaryExpression).Right);
				return;
			}

			base.Visit(node.Expression);
		}
        public override void VisitExpressionStatement(ExpressionStatement node)
        {
            if (!node.IsAssignmentStatement())
            {
                return;
            }

            BinaryExpression assignExpression = node.Expression as BinaryExpression;
            if(assignExpression.Left.CodeNodeType != CodeNodeType.VariableReferenceExpression ||
                assignExpression.Right.CodeNodeType != CodeNodeType.FieldReferenceExpression)
            {
                return;
            }

            FieldReferenceExpression targetFieldRefExpression = assignExpression.Right as FieldReferenceExpression;
            if(targetFieldRefExpression.Target == null ||
                targetFieldRefExpression.Target.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                targetFieldRefExpression.Field.Name != "Target")
            {
                return;
            }

            FieldDefinition callSiteField = (targetFieldRefExpression.Target as FieldReferenceExpression).Field.Resolve();
            CallSiteInfo callSiteInfo;
            if(callSiteField == null || !fieldToCallSiteInfoMap.TryGetValue(callSiteField, out callSiteInfo))
            {
                return;
            }

            variableToCallSiteInfoMap.Add((assignExpression.Left as VariableReferenceExpression).Variable, callSiteInfo);
            statementsToRemove.Add(node);
        }
 public override ICodeNode VisitExpressionStatement(ExpressionStatement node)
 {
     if (CheckVariableInitialization(node))
     {
         return node;
     }
     return base.VisitExpressionStatement(node);
 }
		//x = cond ? y : z;
		//
		//==
		//
		//if(cond)
		//{
		//      x = y;
		//}
		//else
		//{
		//      x = z;
		//}
		//
		//x - phi variable
		//y, z - expressions

		public bool TryMatchInternal(IfStatement theIfStatement, out Statement result)
		{
			result = null;

			if (theIfStatement == null)
			{
				return false;
			}

			VariableReference xVariableReference = null;
			VariableReference x1VariableReference = null;
			Expression yExpressionValue;
			Expression zExpressionValue;

			if (theIfStatement.Else == null ||
				theIfStatement.Then.Statements.Count != 1 || theIfStatement.Else.Statements.Count != 1 ||
				theIfStatement.Then.Statements[0].CodeNodeType != CodeNodeType.ExpressionStatement ||
				theIfStatement.Else.Statements[0].CodeNodeType != CodeNodeType.ExpressionStatement)
			{
				return false;
			}

			BinaryExpression thenAssignExpression = (theIfStatement.Then.Statements[0] as ExpressionStatement).Expression as BinaryExpression;
			BinaryExpression elseAssignExpression = (theIfStatement.Else.Statements[0] as ExpressionStatement).Expression as BinaryExpression;
			if (!IsAssignToVariableExpression(thenAssignExpression, out x1VariableReference) || 
				!IsAssignToVariableExpression(elseAssignExpression, out xVariableReference))
			{
				return false;
			}

			if (xVariableReference != x1VariableReference)
			{
				return false;
			}
			if (!ShouldInlineExpressions(thenAssignExpression, elseAssignExpression))
			{
				/// Although correct syntax, nesting ternary expressions makes the code very unreadable.
				return false;
			}

			yExpressionValue = GetRightExpressionMapped(thenAssignExpression);
            zExpressionValue = GetRightExpressionMapped(elseAssignExpression);

			ConditionExpression ternaryConditionExpression = new ConditionExpression(theIfStatement.Condition, yExpressionValue, zExpressionValue, null);
			BinaryExpression ternaryAssign = new BinaryExpression(BinaryOperator.Assign,
				new VariableReferenceExpression(xVariableReference, null), ternaryConditionExpression, this.typeSystem, null);

            result = new ExpressionStatement(ternaryAssign) { Parent = theIfStatement.Parent };
            FixContext(xVariableReference.Resolve(), 1, 0, result as ExpressionStatement);
			return true;
		}
        protected void FixContext(VariableDefinition variable, int removedDefinitions, int removedUsages, ExpressionStatement newDefinition)
        {
            DefineUseCount defineUseCount;
            if (patternsContext.VariableToDefineUseCountContext.TryGetValue(variable, out defineUseCount))
            {
                defineUseCount.DefineCount -= removedDefinitions;
                defineUseCount.UseCount -= removedUsages;

                if (defineUseCount.DefineCount == 1 && newDefinition != null)
                {
                    patternsContext.VariableToSingleAssignmentMap[variable] = newDefinition;
                }
            }
        }
 public override void VisitExpressionStatement(ExpressionStatement node)
 {
     if (node.IsAssignmentStatement() && node.Parent.CodeNodeType == CodeNodeType.BlockStatement)
     {
         BinaryExpression assignment = node.Expression as BinaryExpression;
         if (assignment.Left.CodeNodeType == CodeNodeType.VariableReferenceExpression)
         {
             Visit(assignment.Right);
             AddDefinition((assignment.Left as VariableReferenceExpression).Variable.Resolve(), node);
             return;
         }
     }
     base.VisitExpressionStatement(node);
 }
 public override void VisitExpressionStatement(ExpressionStatement node)
 {
     if (node.Expression is BinaryExpression)
     {
         BinaryExpression binEx = node.Expression as BinaryExpression;
         if (binEx.Operator == BinaryOperator.Assign)
         {
             if (binEx.Left is VariableReferenceExpression && binEx.Right is VariableReferenceExpression)
             {
                 VariableReference leftVariable = (binEx.Left as VariableReferenceExpression).Variable;
                 VariableReference rightVariable = (binEx.Right as VariableReferenceExpression).Variable;
                 if (leftVariable == rightVariable)
                 {
                     statementsToRemove.Add(node);
                 }
             }
         }
     }
 }
		public bool IsOptimisableAssignment(ExpressionStatement statement)
		{
			BinaryExpression expr = statement.Expression as BinaryExpression;
			if (expr == null)
			{
				return false;
			}
			if (!expr.IsAssignmentExpression)
			{
				return false;
			}
			if (expr.Right.CodeNodeType == CodeNodeType.BinaryExpression &&
				((expr.Right as BinaryExpression).IsAssignmentExpression || (expr.Right as BinaryExpression).IsSelfAssign))
			{
				return false;
			}
			if (expr.Left is VariableReferenceExpression || expr.Left is VariableDeclarationExpression)
			{
				return !new SideEffectsFinder().HasSideEffectsRecursive(expr.Right);
			}
			return false;
		}
 public override ICodeNode VisitExpressionStatement(ExpressionStatement node)
 {
     if (node.Expression.CodeNodeType == CodeNodeType.BinaryExpression)
     {
         BinaryExpression binary = node.Expression as BinaryExpression;
         if (binary.IsAssignmentExpression )
         {
             if (binary.Left.CodeNodeType == CodeNodeType.VariableReferenceExpression)
             {
                 RecordVariableAssignment(node);
                 return node;
             }
             else if (binary.Left.CodeNodeType == CodeNodeType.ArrayIndexerExpression)
             {
                 if (TryUpdateInitializer(node))
                 {
                     return node;
                 }
             }
         }
     }
     return base.VisitExpressionStatement(node);
 }
 public override void VisitExpressionStatement(ExpressionStatement node)
 {
     ProcessExpression(node.Expression);
 }
        //x = y ?? z;
        //
        //==
        //
        //x = y;
        //if(x == null)
        //{
        //      dummyVar = x;
        //      x = z;
        //}
        //
        //x - stack variable
        //y, z - expressions
        //dummyVar - dummy variable(this assignment might be missing)
        private bool TryMatchInternal(StatementCollection statements, int startIndex, out Statement result)
        {
            result = null;
            if (statements.Count < startIndex + 2)
            {
                return false;
            }

            VariableReference xVariableReference;
            Expression yExpressionValue;
            Expression zExpressionValue;

            if (statements[startIndex].CodeNodeType != CodeNodeType.ExpressionStatement ||
                statements[startIndex + 1].CodeNodeType != CodeNodeType.IfStatement)
            {
                return false;
            }
            if (!string.IsNullOrEmpty(statements[startIndex + 1].Label))
            {
                return false;
            }

            BinaryExpression yToXAssingExpression = (statements[startIndex] as ExpressionStatement).Expression as BinaryExpression;
            if (!IsAssignToVariableExpression(yToXAssingExpression, out xVariableReference))
            {
                return false;
            }

            yExpressionValue = yToXAssingExpression.Right;

            IfStatement theIfStatement = statements[startIndex + 1] as IfStatement;
            int zToXAssignIndex = ContainsDummyAssignment(theIfStatement.Then, xVariableReference) ? 1 : 0;
            if (theIfStatement.Else != null || theIfStatement.Then.Statements.Count != 1 + zToXAssignIndex ||
                theIfStatement.Then.Statements[zToXAssignIndex].CodeNodeType != CodeNodeType.ExpressionStatement
                || !string.IsNullOrEmpty(theIfStatement.Then.Statements[zToXAssignIndex].Label))
            {
                return false;
            }

            BinaryExpression theCondition = theIfStatement.Condition as BinaryExpression;
            if (theCondition == null || theCondition.Operator != BinaryOperator.ValueEquality ||
                theCondition.Left.CodeNodeType != CodeNodeType.VariableReferenceExpression ||
                (theCondition.Left as VariableReferenceExpression).Variable != xVariableReference ||
                theCondition.Right.CodeNodeType != CodeNodeType.LiteralExpression ||
                (theCondition.Right as LiteralExpression).Value != null)
            {
                return false;
            }

            BinaryExpression zToXAssignExpression = (theIfStatement.Then.Statements[zToXAssignIndex] as ExpressionStatement).Expression as BinaryExpression;
            VariableReference zVariable;
            if (zToXAssignExpression == null || !IsAssignToVariableExpression(zToXAssignExpression, out zVariable) ||
                zVariable != xVariableReference)
            {
                return false;
            }

            zExpressionValue = zToXAssignExpression.Right;

            if (!yExpressionValue.HasType || !zExpressionValue.HasType || yExpressionValue.ExpressionType.FullName != zExpressionValue.ExpressionType.FullName)
            {
                return false;
            }
            

            BinaryExpression nullCoalescingEpxression = new BinaryExpression(BinaryOperator.NullCoalesce, yExpressionValue, zExpressionValue, typeSystem, null);
            BinaryExpression nullCoalescingAssign = new BinaryExpression(BinaryOperator.Assign,
                new VariableReferenceExpression(xVariableReference, null), nullCoalescingEpxression, typeSystem, null);

            result = new ExpressionStatement(nullCoalescingAssign) { Parent = statements[startIndex].Parent };

            FixContext(xVariableReference.Resolve(), 1, zToXAssignIndex + 1, result as ExpressionStatement);

            return true;
        }
        private bool TryRemoveExpressionStatment(ExpressionStatement statement)
        {
            BlockStatement blockParent = statement.Parent as BlockStatement;
            if (blockParent == null)
            {
                return false;
            }

            blockParent.Statements.Remove(statement);
            return true;
        }
        private void RecordVariableAssignment(ExpressionStatement node)
        {
            BinaryExpression assignment = node.Expression as BinaryExpression;
            VariableReference variable = (assignment.Left as VariableReferenceExpression).Variable;
            assignment.Right = (Expression)Visit(assignment.Right);
            Expression rightClone = assignment.Right.CloneExpressionOnly();
            this.variableToValueMap[variable] = rightClone;

            HashSet<ExpressionStatement> statements;
            if (!this.variableToAssigingStatementsMap.TryGetValue(variable, out statements))
            {
                statements = new HashSet<ExpressionStatement>();
                this.variableToAssigingStatementsMap[variable] = statements;
            }

            statements.Add(node);

            ArrayCreationExpression arrayCreation = rightClone as ArrayCreationExpression;
            if (arrayCreation == null || arrayCreation.Dimensions == null || arrayCreation.Dimensions.Count != 1 || arrayCreation.Initializer != null && arrayCreation.Initializer.Expressions != null &&
                arrayCreation.Initializer.Expressions.Count > 0)
            {
                return;
            }

			var blockExpression = new BlockExpression(null);
			arrayCreation.Initializer = new InitializerExpression(blockExpression, InitializerType.ArrayInitializer);
			this.variableToLastUninitializedIndex[variable] = 0;
        }
        private bool TryUpdateInitializer(ExpressionStatement node)
        {
            BinaryExpression assignment = node.Expression as BinaryExpression;
            ArrayIndexerExpression indexerExpression = assignment.Left as ArrayIndexerExpression;

            if (indexerExpression.Target == null || indexerExpression.Target.CodeNodeType != CodeNodeType.VariableReferenceExpression)
            {
                return false;
            }

            VariableReference variable = (indexerExpression.Target as VariableReferenceExpression).Variable;

            int lastUninitializedIndex;
            if (!this.variableToLastUninitializedIndex.TryGetValue(variable, out lastUninitializedIndex))
            {
                return false;
            }

            if (indexerExpression.Indices == null || indexerExpression.Indices.Count != 1)
            {
                return false;
            }

            int index = GetIntegerValue(indexerExpression.Indices[0] as LiteralExpression);
            if (index != lastUninitializedIndex)
            {
                this.variableToLastUninitializedIndex.Remove(variable);
                this.variableToValueMap.Remove(variable);
                this.variableToAssigingStatementsMap.Remove(variable);

                if (this.usedVariables.Contains(variable))
                {
                    this.failure = true;
                }
                return false;
            }

            ArrayCreationExpression arrayCreation = this.variableToValueMap[variable] as ArrayCreationExpression;
            arrayCreation.Initializer.Expressions.Add((Expression)Visit(assignment.Right.CloneExpressionOnly()));
            this.variableToAssigingStatementsMap[variable].Add(node);
            this.variableToLastUninitializedIndex[variable] = index + 1;
            return true;
        }
 public override void VisitExpressionStatement(ExpressionStatement node)
 {
     if (!assignments.Contains(node))
     {
         base.VisitExpressionStatement(node);
     }
 }
        /// <summary>
        /// Declare boolean variable for each label, and include <code>variable = false;</code> statements just after the label.
        /// Moves the label from the original statement to the variable assignment.
        /// </summary>
        private void AddLabelVariables()
        {
            List<Statement> oldLabels = new List<Statement>(methodContext.GotoLabels.Values);
            foreach (Statement oldLabel in oldLabels)
            {
                string label = oldLabel.Label;
                oldLabel.Label = string.Empty;
                VariableDefinition labelVariable = GetLabelVariable(label);

                ///Add cond = false expression right after the label.
                BlockStatement containingBlock = oldLabel.Parent as BlockStatement;
                ///All labeled statements must be inside BlockStatement.
                if (containingBlock == null)
                {
                    throw new ArgumentOutOfRangeException("Label target is not within a block.");
                }

                int labelIndex = containingBlock.Statements.IndexOf(oldLabel);
                ///Generate the <code>variable=false;</code> statement;
                BinaryExpression assignment =
                    new BinaryExpression(BinaryOperator.Assign, new VariableReferenceExpression(labelVariable, null), GetLiteralExpression(false), typeSystem, null);
                assignment.Right.ExpressionType = methodContext.Method.Module.TypeSystem.Boolean;
                ExpressionStatement assignmentStatement = new ExpressionStatement(assignment);
                ///Add the label to the new assignment
                assignmentStatement.Label = label;
                methodContext.GotoLabels[label] = assignmentStatement;
                ///Push the assignment just before the old labeled statement
                variableToAssignment.Add(labelVariable, assignmentStatement);
                containingBlock.AddStatementAt(labelIndex, assignmentStatement);
            }
        }
        protected bool TryGetAssignedVariable(ExpressionStatement node, out VariableReference variable)
        {
            variable = null;

            Expression variableExpression;
            BinaryExpression assign = node.Expression as BinaryExpression;
            if (assign != null && !assign.IsAssignmentExpression)
            {
                assign = null;
            }

            if (assign == null)
            {
                UnaryExpression unaryExpression = node.Expression as UnaryExpression;
                if (unaryExpression == null ||
                        unaryExpression.Operator != UnaryOperator.PostDecrement &&
                        unaryExpression.Operator != UnaryOperator.PostIncrement &&
                        unaryExpression.Operator != UnaryOperator.PreDecrement &&
                        unaryExpression.Operator != UnaryOperator.PreIncrement)
                {
                    return false;
                }

                variableExpression = unaryExpression.Operand;
            }
            else
            {
                variableExpression = assign.Left;
            }

            if (variableExpression.CodeNodeType == CodeNodeType.VariableDeclarationExpression)
            {
                variable = ((VariableDeclarationExpression)variableExpression).Variable;
            }
            else if (variableExpression.CodeNodeType == CodeNodeType.VariableReferenceExpression)
            {
                variable = ((VariableReferenceExpression)variableExpression).Variable;
            }

            return variable != null;
        }
		private void WriteSplitPropertySetter(PropertyDefinition property)
		{
			WriteKeyword(KeyWordWriter.Set);
			WriteBeginBlock();
			WriteLine();
			Indent();
			MethodReferenceExpression jdSetterReference = new MethodReferenceExpression(null, property.SetMethod, null);
			MethodInvocationExpression jdMethodInvocation = new MethodInvocationExpression(jdSetterReference, null);
			jdMethodInvocation.Arguments = CopyMethodParametersAsArguments(property.SetMethod);
			ExpressionStatement toWrite = new ExpressionStatement(jdMethodInvocation);
			Write(toWrite);
			WriteLine();
			Outdent();
			WriteEndBlock("Set");
		}
 private void ClearState()
 {
     insideTry = false;
     foundEnumeratorAssignment = false;
     foundWhile = false;
     foreachCollection = null;
     foreachVariable = null;
     foreachVariableInstructions.Clear();
     foreachCollectionInstructions.Clear();
     foreachBody = new BlockStatement();
     theEnumerator = null;
     theTry = null;
     @foreach = null;
     enumeratorAssignmentStatement = null;
     foreachVariableType = null;
     isEnumeratorUsedInsideForEach = false;
     foreachConditionInstructions = null;
 }
        /// <summary>
        /// Eliminates the goto statement via introducing do-while. Should be used when the goto comes after the label.
        /// </summary>
        /// <param name="gotoStatement">The goto statement.</param>
        /// <param name="labeledStatement">The labeled statement.</param>
        private void EliminateViaDoWhile(IfStatement gotoStatement, Statement labeledStatement)
        {
            ICollection<BreakStatement> breaks = new List<BreakStatement>();
            ICollection<ContinueStatement> continues = new List<ContinueStatement>();
            BlockStatement containingBlock = GetOuterBlock(labeledStatement);

            int labelIndex = containingBlock.Statements.IndexOf(labeledStatement);
            int gotoIndex = containingBlock.Statements.IndexOf(gotoStatement);
            BlockStatement loopBody = CollectStatements(labelIndex, gotoIndex, containingBlock);

            /// Checks if the gotoStatement is inside a loop/switch statement.
            /// If so, then some breaks might be enclosed in the new do-while. Additional breaks need to be included in this case
            if (ShouldCheck(gotoStatement))
            {
                ContinueAndBreakFinder finder = new ContinueAndBreakFinder();
                finder.Visit(loopBody);
                breaks = finder.Breaks;
                continues = finder.Continues;
            }

            /// Add condition = true before each enclosed break statement.
            foreach (BreakStatement statement in breaks)
            {
                BlockStatement breakBlock = GetOuterBlock(statement);
                int breakIndex = breakBlock.Statements.IndexOf(statement);
                BinaryExpression assign =
                    new BinaryExpression(BinaryOperator.Assign, new VariableReferenceExpression(breakVariable, null), GetLiteralExpression(true), typeSystem, null);
                usedBreakVariable = true;
                ExpressionStatement assignment = new ExpressionStatement(assign);
                breakBlock.AddStatementAt(breakIndex, assignment);
            }

            /// Add condition = true before each enclosed continue statement
            /// and replace the continue statement with break statement
            foreach (ContinueStatement statement in continues)
            {
                BlockStatement continueBlock = GetOuterBlock(statement);
                int continueIndex = continueBlock.Statements.IndexOf(statement);
                BinaryExpression assign =
                    new BinaryExpression(BinaryOperator.Assign, new VariableReferenceExpression(continueVariable, null), GetLiteralExpression(true), typeSystem, null);
                usedContinueVariable = true;
                ExpressionStatement assignment = new ExpressionStatement(assign);
                continueBlock.Statements.RemoveAt(continueIndex);
                continueBlock.AddStatementAt(continueIndex, new BreakStatement(null));
                continueBlock.AddStatementAt(continueIndex, assignment);
            }

            /// Replace the goto with do-while loop.
            DoWhileStatement doWhileLoop = new DoWhileStatement(gotoStatement.Condition, loopBody);
            gotoIndex = containingBlock.Statements.IndexOf(gotoStatement);
            containingBlock.AddStatementAt(gotoIndex, doWhileLoop);
            containingBlock.Statements.Remove(gotoStatement);

            if (breaks.Count > 0)
            {
                /// Add condition for the outer break, accounting for the enclosed breaks.
                AddBreakContinueConditional(gotoIndex + 1, containingBlock, new BreakStatement(null), breakVariable);//gotoindex + 1 should be the place after the newly inserted do-while loop
            }
            if (continues.Count > 0)
            {
                /// Add condition for the outer break, accounting for the enclosed continues.
                AddBreakContinueConditional(gotoIndex + 1, containingBlock, new ContinueStatement(null), continueVariable);
            }
        }
		private void TransferLabel(ExpressionStatement expressionStatement)
		{
			if (expressionStatement.Label == string.Empty)
			{
				return;
			}

			string theLabel = expressionStatement.Label;
			Statement currentStatement = expressionStatement;
			while (currentStatement.Parent != null)
			{
				BlockStatement parent = currentStatement.Parent as BlockStatement;
				int statementIndex = parent.Statements.IndexOf(currentStatement);
				if (statementIndex != parent.Statements.Count - 1)
				{
					Statement nextStatement = parent.Statements[statementIndex + 1];
					MoveLabel(nextStatement, theLabel);
					return;
				}
				else if (IsLoopBody(parent))
				{
					Statement firstStatement = parent.Statements[0];
					MoveLabel(firstStatement, theLabel);
					return;
				}

				do
				{
					currentStatement = currentStatement.Parent;
				}
				while (currentStatement.Parent != null && currentStatement.Parent.CodeNodeType != CodeNodeType.BlockStatement);
			}

			EmptyStatement emptyStatement = new EmptyStatement();
			this.theBody.Statements.Add(emptyStatement);

			MoveLabel(emptyStatement, theLabel);
		}
		public void CleanUpUnusedDeclarations()
		{
			foreach (KeyValuePair<VariableReference, ExpressionStatement> referenceToStatementPair in referenceToDeclarationStatementMap)
			{
				VariableReference variableReference = referenceToStatementPair.Key;
				context.MethodContext.RemoveVariable(variableReference);

				ExpressionStatement declarationStatement = referenceToStatementPair.Value;
				BlockStatement parentBlock = declarationStatement.Parent as BlockStatement;

				if (IsOptimisableAssignment(declarationStatement))
				{
					TransferLabel(declarationStatement);
					parentBlock.Statements.Remove(declarationStatement);
				}
				else
				{
					/// check if the right side can exist on its own
					Expression rightSide = (declarationStatement.Expression as BinaryExpression).Right;
					if (CanExistInStatement(rightSide))
					{
						if (rightSide.CodeNodeType == CodeNodeType.ParenthesesExpression)
						{
							rightSide = (rightSide as ParenthesesExpression).Expression;
						}
						ExpressionStatement newStatement = new ExpressionStatement(rightSide);
						int index = parentBlock.Statements.IndexOf(declarationStatement);
						parentBlock.AddStatementAt(index + 1, newStatement);
						TransferLabel(declarationStatement);
						parentBlock.Statements.RemoveAt(index);
					}
				}
			}

			HashSet<VariableDefinition> unusedVariables = new HashSet<VariableDefinition>();
			foreach (VariableDefinition variable in context.MethodContext.Variables)
			{
				if (!bannedVariables.Contains(variable))
				{
					unusedVariables.Add(variable);
				}
			}

			foreach (VariableDefinition variable in unusedVariables)
			{
				context.MethodContext.RemoveVariable(variable);
			}
		}
		private bool IsFieldAssignment(ExpressionStatement fieldAssignmentStatement, out Expression assignedValue, out string fieldFullName)
		{
            fieldFullName = null;
			assignedValue = null;
			BinaryExpression theFieldAssignment = fieldAssignmentStatement.Expression as BinaryExpression;
			if (theFieldAssignment == null || !theFieldAssignment.IsAssignmentExpression || theFieldAssignment.Left.CodeNodeType != CodeNodeType.FieldReferenceExpression)
			{
				return false;
			}

			FieldReference theField = (theFieldAssignment.Left as FieldReferenceExpression).Field;
			if (theField == null)
			{
				return false;
			}

			assignedValue = theFieldAssignment.Right;
            fieldFullName = theField.FullName;

			return true;
		}
 private bool CheckTheInitializer(ExpressionStatement statement, out VariableReference forVariable)
 {
     forVariable = null;
     return statement != null && statement.IsAssignmentStatement() && TryGetAssignedVariable(statement, out forVariable);
 }
        private bool IsAutoPropertyAssignment(ExpressionStatement propertyAssignmentStatement, out Expression assignedValue, out string propertyFullName)
        {
            propertyFullName = null;
            assignedValue = null;
            BinaryExpression thePropertyAssignment = propertyAssignmentStatement.Expression as BinaryExpression;
            if (thePropertyAssignment == null || !thePropertyAssignment.IsAssignmentExpression || thePropertyAssignment.Left.CodeNodeType != CodeNodeType.AutoPropertyConstructorInitializerExpression)
            {
                return false;
            }

            PropertyDefinition theProperty = (thePropertyAssignment.Left as AutoPropertyConstructorInitializerExpression).Property;
            if (theProperty == null)
            {
                return false;
            }

            assignedValue = thePropertyAssignment.Right;
            propertyFullName = theProperty.FullName;

            return true;
        }
        /// <summary>
        /// Extracts the condition of the condition statement into new variable. Replaces the condition of the statement with the new variable and inserts 
        /// the assignment statement right before the condition statement.
        /// </summary>
        /// <param name="conditionVar">The variable which should be assigned the condition.</param>
        /// <param name="gotoStatement">The conditional goto.</param>
        /// <param name="containingBlock">The block that contains the conditional goto.</param>
        private void ExtractConditionIntoVariable(VariableReferenceExpression conditionVar, ConditionStatement statement, BlockStatement containingBlock)
        {
            /// Create the statement conditionVariable = originalCondition;
            BinaryExpression conditionAssignment = new BinaryExpression(BinaryOperator.Assign, conditionVar, statement.Condition, typeSystem, null);
            ExpressionStatement assignStatement = new ExpressionStatement(conditionAssignment);

            /// Insert the statement before the original goto statement.
            int gotoIndex = containingBlock.Statements.IndexOf(statement);
            containingBlock.AddStatementAt(gotoIndex, assignStatement);

            /// Update the condition of the goto statement.
            statement.Condition = conditionVar.CloneExpressionOnly();
        }
		public override void VisitExpressionStatement(ExpressionStatement node)
		{
			Visit(node.Expression);
			if ((ShouldOmitSemicolon.Count == 0) || (!ShouldOmitSemicolon.Peek()))
			{
				WriteEndOfStatement();
			}
		}
        private bool CheckVariableInitialization(ExpressionStatement node)
        {
            if (!node.IsAssignmentStatement())
            {
                return false;
            }

            BinaryExpression theAssignExpression = node.Expression as BinaryExpression;

            if (theAssignExpression.Left.CodeNodeType != CodeNodeType.VariableReferenceExpression)
            {
                return false;
            }

            Expression value = theAssignExpression.Right;
            if (value.CodeNodeType == CodeNodeType.CastExpression)
            {
                value = (value as CastExpression).Expression;
            }

            if ((value.CodeNodeType != CodeNodeType.LiteralExpression || (value as LiteralExpression).Value != null) &&
                (value.CodeNodeType != CodeNodeType.FieldReferenceExpression))
            {
                return false;
            }

            if (value.CodeNodeType == CodeNodeType.FieldReferenceExpression)
            {
                FieldReferenceExpression fieldReferenceExpression = value as FieldReferenceExpression;
                
                TypeDefinition fieldType = fieldReferenceExpression.ExpressionType.Resolve();
                if (fieldType == null || fieldType.BaseType == null || fieldType.BaseType.FullName != "System.MulticastDelegate")
                {
                    return false;
                }

                // Slow checks
                FieldDefinition fieldDef = fieldReferenceExpression.Field.Resolve();
                if ((fieldDef.DeclaringType != this.context.MethodContext.Method.DeclaringType &&
                    !fieldDef.DeclaringType.IsNestedIn(this.context.MethodContext.Method.DeclaringType)) ||
                    !fieldDef.DeclaringType.IsCompilerGenerated())
                {
                    return false;
                }
            }

            initializationsToRemove[(theAssignExpression.Left as VariableReferenceExpression).Variable] = node;
            return true;
        }
        public override void VisitExpressionStatement(ExpressionStatement node)
        {
            if (!foundWhile)
            {
                if (IsEnumeratorAssignment(node.Expression))
                {
                    foundEnumeratorAssignment = true;
                    enumeratorAssignmentStatement = node;
                    return;
                }
            }
            else
            {
                if (node.Expression is BinaryExpression)
                {
                    if (!IsForeachVariableAssignment(node.Expression as BinaryExpression))
                    {
                        if (shouldAdd)
                        {
                            foreachBody.AddStatement(node);
                        }
                    }
                }
                else if (node.Expression is MethodInvocationExpression || node.Expression is PropertyReferenceExpression)
                {
                    if (IsGetCurrent(node.Expression))
                    {
                        //covers the case where the foreach variable is not used
                        this.foreachVariableType = node.Expression.ExpressionType;
                    }
                    else
                    {
                        if (shouldAdd)
                        {
                            foreachBody.AddStatement(node);
                        }
                    }
                }
                else if (node.Expression is CastExpression)
                {
                    CastExpression theCast = node.Expression as CastExpression;
                    if (IsGetCurrent(theCast.Expression))
                    {
                        this.foreachVariableType = theCast.ExpressionType;
                    }
                    else
                    {
                        if (shouldAdd)
                        {
                            foreachBody.AddStatement(node);
                        }
                    }
                }
                else if (node.Expression is BoxExpression)
                {
                    BoxExpression theBox = node.Expression as BoxExpression;
                    if (IsGetCurrent(theBox.BoxedExpression))
                    {
                        this.foreachVariableType = theBox.BoxedAs;
                    }
                    else
                    {
                        if (shouldAdd)
                        {
                            foreachBody.AddStatement(node);
                        }
                    }

                }
                else
                {
                    if (shouldAdd)
                    {
                        foreachBody.AddStatement(node);
                    }
                }
            }
        }
        protected override ICodeNode GetIfSubstitution(IfStatement node)
        {
            BinaryExpression condition = node.Condition as BinaryExpression;
            if (condition.Left.CodeNodeType != CodeNodeType.FieldReferenceExpression)
            {
                return null;
            }

            FieldReferenceExpression fieldReference = condition.Left as FieldReferenceExpression;
            FieldDefinition fieldDefinition = fieldReference.Field.Resolve();
            if (!this.fieldToReplacingExpressionMap.ContainsKey(fieldDefinition))
            {
                throw new Exception("Caching field not found.");
            }

            VariableDefinition newVariable = new VariableDefinition(fieldDefinition.FieldType);
            VariableReferenceExpression newVariableReference = new VariableReferenceExpression(newVariable, null);
            BinaryExpression newAssignment = new BinaryExpression(BinaryOperator.Assign, newVariableReference, this.fieldToReplacingExpressionMap[fieldDefinition],
                                                                  this.context.MethodContext.Method.Module.TypeSystem, null);
            ExpressionStatement newStatement = new ExpressionStatement(newAssignment);

            this.initializationsToRemove.Add(newVariable, newStatement);

            this.variableToReplacingExpressionMap.Add(newVariable, this.fieldToReplacingExpressionMap[fieldDefinition]);
            this.fieldToReplacingExpressionMap[fieldDefinition] = newVariableReference;

            this.context.MethodContext.Variables.Add(newVariable);
            this.context.MethodContext.VariablesToRename.Add(newVariable);

            return newStatement;
        }