private void ChangeVariableState(Step state, VariableReferenceExpression node)
        {
            VariableStateAndExpression variableStateAndExpression = GetValue(node.Variable);

            if ((state == Step.Expression) &&
                (variableStateAndExpression.VariableState != VariableState.Other) &&
                variableStateAndExpression.NumberOfTimesAssigned <= 1)
            {
                variableStateAndExpression.VariableState = VariableState.Condition;
            }
            else if (state == Step.Assign)
            {
                if (variableStateAndExpression.VariableState == VariableState.Condition)
                {
                    variableStateAndExpression.VariableState = VariableState.Assign | VariableState.Condition;
                }
                else
                {
                    variableStateAndExpression.VariableState = VariableState.Assign;
                    variableStateAndExpression.NumberOfTimesAssigned++;
                }
            }
            else
            {
                variableStateAndExpression.VariableState = VariableState.Other;
            }
        }
        public override void VisitVariableReferenceExpression(VariableReferenceExpression node)
        {
            if (processStep == ProcessStep.Replace)
            {
                return;
            }

            var state = states.Peek();

            if (ContainsKey(node.Variable))
            {
                ChangeVariableState(state, node);
            }
            else
            {
                VariableState variableState = GetInitialVariableState(state);
                var           variableStateAndExpression = new VariableStateAndExpression(node.Variable, variableState);
                if (state == Step.Assign)
                {
                    variableStateAndExpression.NumberOfTimesAssigned++;
                }
                variables.Add(variableStateAndExpression);
            }
            base.VisitVariableReferenceExpression(node);

            this.currentVariable = node.Variable;
        }
        private void RemoveNotSetStatementExpressions(VariableStateAndExpression keyValuePair, HashSet <VariableStateAndExpression> variablesToRemove)
        {
            var statementExpressions = new Stack <StatementExpression>(keyValuePair.StatementExpressions);

            keyValuePair.StatementExpressions.Clear();
            foreach (var statementExpression in statementExpressions)
            {
                if (statementExpression.Statement != null)
                {
                    if (statementExpression.ParentWhileStatement != null)
                    {
                        int index = GetParentWhileStatementIndex(keyValuePair.StatementExpressions, statementExpression.ParentWhileStatement);
                        keyValuePair.StatementExpressions.Insert(index, statementExpression);
                    }
                    else
                    {
                        keyValuePair.StatementExpressions.Add(statementExpression);
                    }
                }
            }
            if (keyValuePair.StatementExpressions.Count == 0)
            {
                variablesToRemove.Add(keyValuePair);
            }
        }
        private bool TryGetValue(VariableReference variableReference, out VariableStateAndExpression variableStateAndExpression)
        {
            var result = variables.Where(v => v.VariableReference == variableReference).FirstOrDefault();

            variableStateAndExpression = result;
            return(result != null);
        }
        private Expression GetCurrentStatementExpression(VariableStateAndExpression variableStateAndExpression)
        {
            if (variableStateAndExpression.StatementExpressions.Count == 0)
            {
                return(null);
            }

            var lastStatementExpression = variableStateAndExpression.StatementExpressions[variableStateAndExpression.StatementExpressions.Count - 1];

            variableStateAndExpression.StatementExpressions.Remove(lastStatementExpression);
            return(lastStatementExpression.Expression.CloneExpressionOnly());
        }
		private Expression GetCurrentStatementExpression(VariableStateAndExpression variableStateAndExpression)
		{
			if (variableStateAndExpression.StatementExpressions.Count == 0)
				return null;

			var lastStatementExpression = variableStateAndExpression.StatementExpressions[variableStateAndExpression.StatementExpressions.Count - 1];
			variableStateAndExpression.StatementExpressions.Remove(lastStatementExpression);
			return lastStatementExpression.Expression.CloneExpressionOnly();
		}
		public override void VisitVariableReferenceExpression(VariableReferenceExpression node)
		{
			if (processStep == ProcessStep.Replace)
				return;

			var state = states.Peek();
			if (ContainsKey(node.Variable))
			{
				ChangeVariableState(state, node);
			}
			else
			{
				VariableState variableState = GetInitialVariableState(state);
				var variableStateAndExpression = new VariableStateAndExpression(node.Variable, variableState);
                if (state == Step.Assign)
                {
                    variableStateAndExpression.NumberOfTimesAssigned++;
                }
				variables.Add(variableStateAndExpression);
			}
			base.VisitVariableReferenceExpression(node);

            this.currentVariable = node.Variable;
		}
		private void RemoveNotSetStatementExpressions(VariableStateAndExpression keyValuePair, HashSet<VariableStateAndExpression> variablesToRemove)
		{
			var statementExpressions = new Stack<StatementExpression>(keyValuePair.StatementExpressions);
			keyValuePair.StatementExpressions.Clear();
			foreach (var statementExpression in statementExpressions)
			{
				if (statementExpression.Statement != null)
				{
					if (statementExpression.ParentWhileStatement != null)
					{
						int index = GetParentWhileStatementIndex(keyValuePair.StatementExpressions, statementExpression.ParentWhileStatement);
						keyValuePair.StatementExpressions.Insert(index, statementExpression);
					}
					else
					{
						keyValuePair.StatementExpressions.Add(statementExpression);
					}
				}
			}
			if (keyValuePair.StatementExpressions.Count == 0)
			{
				variablesToRemove.Add(keyValuePair);
			}
		}
		private bool TryGetValue(VariableReference variableReference, out VariableStateAndExpression variableStateAndExpression)
		{
			var result = variables.Where(v => v.VariableReference == variableReference).FirstOrDefault();
			variableStateAndExpression = result;
			return (result != null);
		}