/// <summary>
        /// Evaluate the type of a phi node.
        /// </summary>
        /// <param name="phi"></param>
        internal static void EvaluatePhiType(Phi phi)
        {
            int allUnreached = 0;
            Type typeSoFar = null;
            bool first = true;

            if (phi.Operands.Length == 0 || phi.DefinedBlock == null)
            {
                return;
            }

            foreach (var operand in phi.Operands)
            {
                var operandDetails = InternalVariablesDictionary[operand.Name];

                if (operandDetails.Type == typeof(Undetermined))
                {
                    typeSoFar = typeof(Undetermined);
                    break;
                }
                else
                {
                    if (first)
                    {
                        first = false;
                        typeSoFar = operandDetails.Type;

                        if (typeSoFar == typeof(Unreached))
                        {
                            allUnreached += 1;
                        }
                    }
                    else
                    {
                        if (operandDetails.Type == typeof(Unreached))
                        {
                            allUnreached += 1;
                        }
                        else if (typeSoFar != operandDetails.Type)
                        {
                            typeSoFar = typeof(Undetermined);
                            break;
                        }
                    }
                }

            }

            if (allUnreached == phi.Operands.Length)
            {
                typeSoFar = typeof(Unreached);
            }

            InternalVariablesDictionary[phi.Name].Type = typeSoFar;

            return;
        }
        /// <summary>
        /// Evaluate the constant value at a phi node
        /// </summary>
        /// <param name="phi"></param>
        internal static void EvaluatePhiConstant(Phi phi)
        {
            int allUnreached = 0;
            object constantSoFar = null;
            bool first = true;

            if (phi.Operands.Length == 0 || phi.DefinedBlock == null)
            {
                return;
            }

            foreach (var operand in phi.Operands)
            {
                var operandDetails = InternalVariablesDictionary[operand.Name];

                if (operandDetails.Constant == Undetermined.UndeterminedConstant)
                {
                    constantSoFar = Undetermined.UndeterminedConstant;
                    break;
                }
                else
                {
                    if (first)
                    {
                        first = false;
                        constantSoFar = operandDetails.Constant;

                        if (constantSoFar == Unreached.UnreachedConstant)
                        {
                            allUnreached += 1;
                        }
                    }
                    else
                    {
                        if (operandDetails.Constant == Unreached.UnreachedConstant)
                        {
                            allUnreached += 1;
                        }
                        else if ((operandDetails.Constant == null && operandDetails.Constant != constantSoFar)
                            || (operandDetails.Constant != null && !operandDetails.Constant.Equals(constantSoFar)))
                        {
                            constantSoFar = Undetermined.UndeterminedConstant;
                            break;
                        }
                    }
                }

            }

            if (allUnreached == phi.Operands.Length)
            {
                constantSoFar = Unreached.UnreachedConstant;
            }

            InternalVariablesDictionary[phi.Name].Constant = constantSoFar;

            return;
        }