// --------------------------------------------------------------------------

        // 1. goto 9
        // 9. goto 21

        // 1. goto 21
        // 9. goto 21

        private void TraceGotoChains()
        {
            for (int index = 1; index < m_middleCodeList.Count; ++index)
            {
                MiddleCode middleCode = m_middleCodeList[index];

                if (middleCode.IsRelationCarryOrGoto())
                {
                    ISet <int> sourceSet = new HashSet <int>();
                    sourceSet.Add(index);

                    int firstTarget = (int)middleCode[0];
                    int finalTarget = TraceGoto(firstTarget, sourceSet);

                    if (firstTarget != finalTarget)
                    {
                        foreach (int source in sourceSet)
                        {
                            MiddleCode sourceCode = m_middleCodeList[source];
                            sourceCode[0] = finalTarget;
                        }

                        m_update = true;
                    }
                }
            }
        }
        public void ObjectToIntegerAddresses()
        {
            IDictionary <MiddleCode, int> addressMap =
                new Dictionary <MiddleCode, int>();

            for (int index = 0; index < m_middleCodeList.Count; ++index)
            {
                MiddleCode middleCode = m_middleCodeList[index];
                addressMap.Add(middleCode, index);
            }

            for (int index = 0; index < m_middleCodeList.Count; ++index)
            {
                MiddleCode sourceCode = m_middleCodeList[index];

                if (sourceCode.IsGoto() || sourceCode.IsCarry() ||
                    sourceCode.IsRelation())
                {
                    Debug.Assert(sourceCode[0] is MiddleCode);
                    MiddleCode targetCode = (MiddleCode)sourceCode[0];
                    Debug.Assert(addressMap.ContainsKey(targetCode));
                    sourceCode[0] = addressMap[targetCode];
                }
            }
        }
        private int TraceGoto(int target, ISet <int> sourceSet)
        {
            MiddleCode objectCode = m_middleCodeList[target];

            if (!sourceSet.Contains(target) && objectCode.IsGoto())
            {
                sourceSet.Add(target);
                int nextTarget = (int)objectCode[0];
                return(TraceGoto(nextTarget, sourceSet));
            }
            else
            {
                return(target);
            }
        }
        private void DereferenceToIndex()
        {
            for (int index = 0; index < (m_middleCodeList.Count - 1); ++index)
            {
                MiddleCode thisCode = m_middleCodeList[index],
                           nextCode = m_middleCodeList[index + 1];

                // *(a + 3) <=> a[3] <=> *(3 + a) <=> 3[a]
                if ((thisCode.Operator == MiddleOperator.Add) &&
                    (nextCode.Operator == MiddleOperator.Dereference) &&
                    (thisCode[0] == nextCode[1]))
                {
                    Symbol leftSymbol  = (Symbol)thisCode[1],
                           rightSymbol = (Symbol)thisCode[2];

                    if (leftSymbol.Value is BigInteger)
                    {
                        Symbol resultSymbol = (Symbol)nextCode[0];
                        resultSymbol.AddressSymbol = rightSymbol;
                        resultSymbol.AddressOffset = ((int)((BigInteger)leftSymbol.Value));
                        thisCode.Clear();
                    }
                    else if (rightSymbol.Value is BigInteger)
                    {
                        Symbol resultSymbol = (Symbol)nextCode[0];
                        resultSymbol.AddressSymbol = leftSymbol;
                        resultSymbol.AddressOffset = ((int)((BigInteger)rightSymbol.Value));
                        thisCode.Clear();
                    }
                }
                // *(a - 3) <=> a[-3]
                else if ((thisCode.Operator == MiddleOperator.Subtract) &&
                         (nextCode.Operator == MiddleOperator.Dereference) &&
                         (thisCode[0] == nextCode[1]))
                {
                    Symbol leftSymbol  = (Symbol)thisCode[1],
                           rightSymbol = (Symbol)thisCode[2];

                    if (rightSymbol.Value is BigInteger)
                    {
                        Symbol resultSymbol = (Symbol)nextCode[0];
                        resultSymbol.AddressSymbol = leftSymbol;
                        resultSymbol.AddressOffset = -((int)((BigInteger)rightSymbol.Value));
                        thisCode.Clear();
                    }
                }
            }
        }
        // Top x + Pop => Pop x

        // top x
        // pop

        // pop x

        public void MergeTopPopEmptyToPop()
        {
            for (int index = 0; index < (m_middleCodeList.Count - 1); ++index)
            {
                MiddleCode thisCode = m_middleCodeList[index],
                           nextCode = m_middleCodeList[index + 1];

                if ((thisCode.Operator == MiddleOperator.TopFloat) &&
                    (nextCode.Operator == MiddleOperator.PopEmpty))
                {
                    thisCode.Operator = MiddleOperator.PopFloat;
                    nextCode.Clear();
                    m_update = true;
                }
            }
        }
        // --------------------------------------------------------------------------

        private void ClearUnreachableCode()
        {
            ISet <MiddleCode> visitedSet = new HashSet <MiddleCode>();

            SearchReachableCode(0, visitedSet);

            for (int index = 0; index < (m_middleCodeList.Count - 1); ++index)
            {
                MiddleCode middleCode = m_middleCodeList[index];
                if (!visitedSet.Contains(middleCode))
                {
                    m_middleCodeList[index].Clear();
                    m_update = true;
                }
            }
        }
        public override bool Equals(Object obj)
        {
            if (obj is MiddleCode)
            {
                MiddleCode middleCode = (MiddleCode)obj;
                return((m_middleOperator == middleCode.m_middleOperator) &&
                       (((m_operandArray[0] == null) && (middleCode.m_operandArray[0] == null)) ||
                        m_operandArray[0].Equals(middleCode.m_operandArray[0])) &&
                       (((m_operandArray[1] == null) && (middleCode.m_operandArray[1] == null)) ||
                        m_operandArray[1].Equals(middleCode.m_operandArray[1])) &&
                       (((m_operandArray[2] == null) && (middleCode.m_operandArray[2] == null)) ||
                        m_operandArray[2].Equals(middleCode.m_operandArray[2])));
            }

            return(false);
        }
        // Push x + Pop => empty

        // push x
        // pop

        // empty

        public void RemovePushPop()
        {
            for (int index = 0; index < (m_middleCodeList.Count - 1); ++index)
            {
                MiddleCode thisCode = m_middleCodeList[index],
                           nextCode = m_middleCodeList[index + 1];
                if ((thisCode.Operator == MiddleOperator.PushFloat) &&
                    ((nextCode.Operator == MiddleOperator.PopEmpty) ||
                     ((nextCode.Operator == MiddleOperator.PopFloat) &&
                      (thisCode[0] == nextCode[0]))))
                {
                    thisCode.Clear();
                    nextCode.Clear();
                    m_update = true;
                }
            }
        }
        // t = a
        // b = t

        // b = a

        private void MergeDoubleAssign()
        {
            for (int index = 0; index < (m_middleCodeList.Count - 1); ++index)
            {
                MiddleCode thisCode = m_middleCodeList[index],
                           nextCode = m_middleCodeList[index + 1];

                if ((thisCode.Operator == MiddleOperator.Assign) &&
                    (nextCode.Operator == MiddleOperator.Assign) &&
                    thisCode[0] == nextCode[1])
                {
                    thisCode[0] = nextCode[0];
                    nextCode.Clear();
                    m_update = true;
                }
            }
        }
        // assign a = b => Pop a

        // a = b
        // pop a

        public void AssignFloat()
        {
            for (int index = 0; index < (m_middleCodeList.Count - 1); ++index)
            {
                MiddleCode middleCode = m_middleCodeList[index];

                if (middleCode.Operator == MiddleOperator.Assign)
                {
                    Symbol resultSymbol = (Symbol)middleCode[1];

                    if (resultSymbol.Type.IsFloating())
                    {
                        middleCode.Operator = MiddleOperator.PopFloat;
                        m_update            = true;
                    }
                }
            }
        }
        // t = b + c
        // a = t

        // a = b + c

        private void MergeBinary()
        {
            for (int index = 0; index < (m_middleCodeList.Count - 1); ++index)
            {
                MiddleCode thisCode = m_middleCodeList[index],
                           nextCode = m_middleCodeList[index + 1];

                if ((/*thisCode.IsUnary() ||*/ thisCode.IsBinary()) &&
                    (nextCode.Operator == MiddleOperator.Assign) &&
                    ((Symbol)thisCode[0]).IsTemporary() &&
                    (thisCode[0] == nextCode[1]))
                {
                    thisCode[0] = nextCode[0];
                    nextCode.Clear();
                    m_update = true;
                }
            }
        }
        // --------------------------------------------------------------------------

        // 1. goto 2
        // 2. ...

        private void ClearGotoNextStatements()
        {
            for (int index = 0; index < (m_middleCodeList.Count - 1); ++index)
            {
                MiddleCode middleCode = m_middleCodeList[index];

                if (middleCode.IsRelationCarryOrGoto())
                {
                    int target = (int)middleCode[0];

                    if (target == (index + 1))
                    {
                        middleCode.Clear();
                        m_update = true;
                    }
                }
            }
        }
        public static Expression Logical(MiddleOperator middleOp,
                                         Expression leftExpression,
                                         Expression rightExpression)
        {
            if (!IsConstant(leftExpression) || !IsConstant(rightExpression))
            {
                return(null);
            }

            bool resultValue = false;

            switch (middleOp)
            {
            case MiddleOperator.LogicalAnd:
                resultValue = IsTrue(leftExpression) && IsTrue(rightExpression);
                break;

            case MiddleOperator.LogicalOr:
                resultValue = IsTrue(leftExpression) || IsTrue(rightExpression);
                break;
            }

            List <MiddleCode> longList = new List <MiddleCode>();
            MiddleCode        jumpCode = new MiddleCode(MiddleOperator.Jump);

            longList.Add(jumpCode);

            ISet <MiddleCode> jumpSet = new HashSet <MiddleCode>();

            jumpSet.Add(jumpCode);

            Symbol resultSymbol = new Symbol(null, null);

            if (resultValue)
            {
                resultSymbol.TrueSet = jumpSet;
            }
            else
            {
                resultSymbol.FalseSet = jumpSet;
            }

            return(new Expression(resultSymbol, null, longList));
        }
        public void Optimize()
        {
            ObjectToIntegerAddresses();

            if (SymbolTable.CurrentFunction.Name.Equals("log"))
            {
                string name = @"C:\Users\Stefa\Documents\vagrant\homestead\code\code\" +
                              SymbolTable.CurrentFunction.Name + ".middlenumber";
                StreamWriter streamWriter = new StreamWriter(name);

                for (int index = 0; index < m_middleCodeList.Count; ++index)
                {
                    MiddleCode middleCode = m_middleCodeList[index];
                    streamWriter.WriteLine(index + ": " + middleCode.ToString());
                }

                streamWriter.Close();
            }

            do
            {
                m_update = false;
                ClearGotoNextStatements();
                ClearDoubleRelationStatements();
                TraceGotoChains();
                ClearUnreachableCode();
                RemovePushPop();
                //MergePopPushToTop();
                MergeTopPopEmptyToPop();
                //AssignFloat(); // XXX
                MergeBinary(); // XXX
                DereferenceToIndex();
                //MergeDoubleAssign(); // XXX
                SematicOptimization();
                //OptimizeRelation(); // XXX
                OptimizeCommutative();
                SwapRelation();
                RemoveTrivialAssign();
                //OptimizeBinary();
                CheckIntegral(); // XXX
                CheckFloating(); // XXX
                RemoveClearedCode();
            } while (m_update);
        }
        private void SearchReachableCode(int index, ISet <MiddleCode> visitedSet)
        {
            for (; index < m_middleCodeList.Count; ++index)
            {
                MiddleCode middleCode = m_middleCodeList[index];

                if (visitedSet.Contains(middleCode))
                {
                    return;
                }

                visitedSet.Add(middleCode);

                if (middleCode.IsRelation() || middleCode.IsCarry())
                {
                    int target = (int)middleCode[0];
                    SearchReachableCode(target, visitedSet);
                }
                else if (middleCode.IsGoto())
                {
                    int target = (int)middleCode[0];
                    SearchReachableCode(target, visitedSet);
                    return;
                }
                else if (middleCode.Operator == MiddleOperator.Return)
                {
                    if (m_middleCodeList[index + 1].Operator == MiddleOperator.Exit)
                    {
                        visitedSet.Add(m_middleCodeList[index + 1]);
                    }

                    return;
                }
                else if (middleCode.Operator == MiddleOperator.FunctionEnd)
                {
                    Symbol funcSymbol = (Symbol)middleCode[0];
                    Error.Check(funcSymbol.Type.ReturnType.IsVoid(),
                                funcSymbol.Name,
                                Message.Reached_the_end_of_a_non__void_function);
                    return;
                }
            }
        }
        private void ClearDoubleRelationStatements()
        {
            for (int index = 0; index < (m_middleCodeList.Count - 1); ++index)
            {
                MiddleCode thisCode = m_middleCodeList[index],
                           nextCode = m_middleCodeList[index + 1];

                if ((thisCode.IsRelation() || thisCode.IsCarry()) &&
                    nextCode.IsGoto())
                {
                    int target1 = (int)thisCode[0],
                        target2 = (int)nextCode[0];

                    if (target1 == (index + 2))
                    {
                        MiddleOperator operator1 = thisCode.Operator;
                        thisCode.Operator = m_inverseMap[operator1];
                        thisCode[0]       = target2;
                        nextCode.Clear();
                        m_update = true;
                    }
                }
            }
        }
        private void CheckFloating()
        {
            int stackSize = 0;

            for (int line = 0; line < m_middleCodeList.Count; ++line)
            {
                MiddleCode middleCode = m_middleCodeList[line];

                object operand0 = middleCode[0],
                       operand1 = middleCode[1],
                       operand2 = middleCode[2];

                Symbol symbol0 = (operand0 is Symbol) ? ((Symbol)operand0) : null,
                       symbol1 = (operand1 is Symbol) ? ((Symbol)operand1) : null,
                       symbol2 = (operand2 is Symbol) ? ((Symbol)operand2) : null;

                switch (middleCode.Operator)
                {
                case MiddleOperator.PreCall:
                    middleCode[2] = stackSize;
                    break;

                case MiddleOperator.PushOne:
                case MiddleOperator.PushZero:
                case MiddleOperator.PushFloat:
                case MiddleOperator.IntegralToFloating:
                    ++stackSize;
                    break;

                case MiddleOperator.GetReturnValue:
                    if (symbol0.Type.IsFloating())
                    {
                        ++stackSize;
                    }
                    break;

                case MiddleOperator.PopFloat:
                case MiddleOperator.FloatingToIntegral:
                case MiddleOperator.DecreaseStack:
                    --stackSize;
                    break;

                case MiddleOperator.Return:
                    stackSize = 0;
                    break;

                case MiddleOperator.Equal:
                case MiddleOperator.NotEqual:
                case MiddleOperator.LessThan:
                case MiddleOperator.LessThanEqual:
                case MiddleOperator.GreaterThan:
                case MiddleOperator.GreaterThanEqual: {
                    if (symbol1.Type.IsFloating())
                    {
                        stackSize -= 2;
                    }
                }
                break;

                case MiddleOperator.Add:
                case MiddleOperator.Subtract:
                case MiddleOperator.Multiply:
                case MiddleOperator.Divide:
                    if (symbol1.Type.IsFloating())
                    {
                        --stackSize;
                    }
                    break;

                case MiddleOperator.Parameter:
                    if (symbol2.Type.IsFloating())
                    {
                        --stackSize;
                    }
                    break;
                }
            }
        }
        private void CheckIntegral()
        {
            Stack <ISet <Symbol> > integralSetStack = new Stack <ISet <Symbol> >();
            ISet <Symbol>          integralSet      = new HashSet <Symbol>();

            for (int line = 0; line < m_middleCodeList.Count; ++line)
            {
                MiddleCode middleCode = m_middleCodeList[line];

                object operand0 = middleCode[0],
                       operand1 = middleCode[1],
                       operand2 = middleCode[2];

                Symbol symbol0 = (operand0 is Symbol) ? ((Symbol)operand0) : null,
                       symbol1 = (operand1 is Symbol) ? ((Symbol)operand1) : null,
                       symbol2 = (operand2 is Symbol) ? ((Symbol)operand2) : null;

                switch (middleCode.Operator)
                {
                case MiddleOperator.Empty:
                    //Debug.Assert((symbol0 == null) && (symbol1 == null) && (symbol2 == null));
                    break;

                case MiddleOperator.PreCall: {
                    middleCode[1] = CloneSet(integralSet);
                    integralSetStack.Push(integralSet);
                    integralSet = new HashSet <Symbol>();
                }
                break;

                case MiddleOperator.PostCall:
                    integralSet = integralSetStack.Pop();
                    break;

                case MiddleOperator.Dereference: {
                    Symbol resultSymbol = (Symbol)middleCode[0];
                    integralSet.Add(resultSymbol.AddressSymbol);
                    //integralSet.Remove(resultSymbol.AddressSymbol);

/*              if (resultSymbol.Switch) {
 *              integralSet.Remove(resultSymbol.AddressSymbol);
 *            }
 *            else {
 *              integralSet.Add(resultSymbol.AddressSymbol);
 *            }*/
                }
                break;

                /*case MiddleOperator.SysCall: {
                 *  List<Pair<Register,Symbol>> outParameterList = SystemCode.OutParameterList();
                 *
                 *  foreach (Pair<Register,Symbol> pair in outParameterList) {
                 *    Symbol outSymbol = pair.Second;
                 *    integralSet.Add(outSymbol);
                 *  }
                 * }
                 * break;*/

                case MiddleOperator.Case:
                    if (symbol1.AddressSymbol != null)
                    {
                        integralSet.Remove(symbol1.AddressSymbol);
                    }
                    break;

                case MiddleOperator.CaseEnd:
                    integralSet.Remove(symbol0);
                    break;

                default:
                    if ((symbol0 != null) && symbol0.IsTemporary() &&
                        (symbol0.AddressSymbol == null) &&
                        symbol0.Type.IsIntegralPointerOrArray())
                    {
                        integralSet.Add(symbol0);
                    }

                    if ((symbol1 != null) && symbol1.IsTemporary() &&
                        symbol1.Type.IsIntegralPointerOrArray())
                    {
                        integralSet.Remove(symbol1);
                    }

                    if ((symbol2 != null) && symbol2.IsTemporary() &&
                        symbol2.Type.IsIntegralPointerOrArray())
                    {
                        integralSet.Remove(symbol2);
                    }

                    if ((symbol0 != null) && (symbol0.AddressSymbol != null))
                    {
                        integralSet.Remove(symbol0.AddressSymbol);
                    }

                    if ((symbol1 != null) && (symbol1.AddressSymbol != null))
                    {
                        integralSet.Remove(symbol1.AddressSymbol);
                    }

                    if ((symbol2 != null) && (symbol2.AddressSymbol != null))
                    {
                        integralSet.Remove(symbol2.AddressSymbol);
                    }
                    break;
                }
            }
        }
        private void SematicOptimization()
        {
            for (int index = 0; index < m_middleCodeList.Count; ++index)
            {
                MiddleCode thisCode = m_middleCodeList[index];

                if (thisCode.IsBinary())
                {
                    Symbol resultSymbol = (Symbol)thisCode[0],
                           leftSymbol   = (Symbol)thisCode[1],
                           rightSymbol  = (Symbol)thisCode[2],
                           newSymbol    = null;

                    if ((leftSymbol.Value is BigInteger) && // t0 = 2 * 3
                        (rightSymbol.Value is BigInteger))
                    {
                        newSymbol =
                            ConstantExpression.ArithmeticIntegral(thisCode.Operator,
                                                                  leftSymbol, rightSymbol);
                    }
                    // t0 = 0 + i
                    else if ((thisCode.Operator == MiddleOperator.Add) &&
                             (leftSymbol.Value is BigInteger) &&
                             (leftSymbol.Value.Equals(BigInteger.Zero)))
                    {
                        newSymbol = rightSymbol;
                    }
                    // t0 = 0 - i; t0 = -i
                    else if ((thisCode.Operator == MiddleOperator.Subtract) &&
                             (leftSymbol.Value is BigInteger) &&
                             (leftSymbol.Value.Equals(BigInteger.Zero)))
                    {
                        thisCode.Operator = MiddleOperator.Minus;
                        thisCode[0]       = thisCode[1];
                        thisCode[1]       = null;
                    }

                    // t0 = i + 0
                    // t0 = i - 0
                    else if (((thisCode.Operator == MiddleOperator.Add) ||
                              (thisCode.Operator == MiddleOperator.Subtract)) &&
                             (rightSymbol.Value is BigInteger) &&
                             (rightSymbol.Value.Equals(BigInteger.Zero)))
                    {
                        newSymbol = leftSymbol;
                    }
                    // t0 = 0 * i
                    else if ((thisCode.Operator == MiddleOperator.Multiply) &&
                             (leftSymbol.Value is BigInteger) &&
                             (leftSymbol.Value.Equals(BigInteger.Zero)))
                    {
                        newSymbol = new Symbol(resultSymbol.Type, BigInteger.Zero);
                    }
                    // t0 = 1 * i
                    else if ((thisCode.Operator == MiddleOperator.Multiply) &&
                             (leftSymbol.Value is BigInteger) &&
                             (leftSymbol.Value.Equals(BigInteger.One)))
                    {
                        newSymbol = rightSymbol;
                    }
                    // t0 = i * 0
                    else if ((thisCode.Operator == MiddleOperator.Multiply) &&
                             (rightSymbol.Value is BigInteger) &&
                             (rightSymbol.Value.Equals(BigInteger.Zero)))
                    {
                        newSymbol = new Symbol(resultSymbol.Type, BigInteger.Zero);
                    }

                    // t0 = -1 * i
                    else if ((thisCode.Operator == MiddleOperator.Multiply) &&
                             (leftSymbol.Value is BigInteger) &&
                             (leftSymbol.Value.Equals(BigInteger.MinusOne)))
                    {
                        thisCode.Operator = MiddleOperator.Minus;
                        thisCode[0]       = thisCode[1];
                        thisCode[1]       = null;
                    }
                    // t0 = i * -1
                    else if ((thisCode.Operator == MiddleOperator.Multiply) &&
                             (rightSymbol.Value is BigInteger) &&
                             (rightSymbol.Value.Equals(BigInteger.MinusOne)))
                    {
                        thisCode.Operator = MiddleOperator.Minus;
                        thisCode[1]       = null;
                    }

                    // t0 = i * 1
                    // t0 = i / 1
                    // t0 = i % 1
                    else if (((thisCode.Operator == MiddleOperator.Multiply) ||
                              (thisCode.Operator == MiddleOperator.Divide) ||
                              (thisCode.Operator == MiddleOperator.Modulo)) &&
                             (rightSymbol.Value is BigInteger) &&
                             (rightSymbol.Value.Equals(BigInteger.One)))
                    {
                        newSymbol = leftSymbol;
                    }

                    if (newSymbol != null)
                    {
                        if (resultSymbol.IsTemporary())
                        {
                            thisCode.Operator = MiddleOperator.Empty;

                            if (newSymbol.IsTemporary())
                            {
                                int index2;
                                for (index2 = (index - 1); index2 >= 0; --index2)
                                {
                                    MiddleCode previousCode = m_middleCodeList[index2];

                                    if (previousCode[0] == resultSymbol)
                                    {
                                        previousCode[0] = newSymbol;
                                        break;
                                    }
                                }
                            }

                            { int index2;
                              for (index2 = index + 1; index2 < m_middleCodeList.Count;
                                   ++index2)
                              {
                                  MiddleCode nextCode = m_middleCodeList[index2];

                                  if (nextCode[0] == resultSymbol)
                                  {
                                      nextCode[0] = newSymbol;
                                  }

                                  if (nextCode[1] == resultSymbol)
                                  {
                                      nextCode[1] = newSymbol;
                                  }

                                  if (nextCode[2] == resultSymbol)
                                  {
                                      nextCode[2] = newSymbol;
                                  }
                              }
                            }
                        }
                        else
                        {
                            thisCode.Operator = MiddleOperator.Assign; // i = 0 + j;
                            thisCode[1]       = newSymbol;             // i = j;
                            thisCode[2]       = null;
                        }

                        m_update = true;
                    }
                }
            }
        }
        public static Expression ConstantCast(Expression sourceExpression,
                                              Type targetType)
        {
            if (!IsConstant(sourceExpression))
            {
                return(null);
            }

            Symbol            sourceSymbol = sourceExpression.Symbol, targetSymbol;
            Type              sourceType  = sourceSymbol.Type;
            object            sourceValue = sourceSymbol.Value;
            List <MiddleCode> longList    = new List <MiddleCode>();

            if (sourceType.IsIntegralOrPointer() && targetType.IsFloating())
            {
                decimal targetValue = ((decimal)((BigInteger)sourceValue));
                targetSymbol = new Symbol(targetType, targetValue);
            }
            else if (sourceType.IsFloating() && targetType.IsIntegralOrPointer())
            {
                BigInteger targetValue = ((BigInteger)((decimal)sourceValue));
                targetSymbol = new Symbol(targetType, targetValue);
            }
            else if (sourceType.IsLogical() && targetType.IsArithmeticOrPointer())
            {
                bool   isTrue = (sourceSymbol.TrueSet.Count > 0);
                object targetValue;

                if (targetType.IsIntegralOrPointer())
                {
                    targetValue = isTrue ? BigInteger.One : BigInteger.Zero;
                }
                else
                {
                    targetValue = isTrue ? decimal.One : decimal.Zero;
                }

                targetSymbol = new Symbol(targetType, targetValue);
            }
            else if (sourceType.IsArithmeticOrPointer() && targetType.IsLogical())
            {
                bool isTrue = !sourceValue.Equals(BigInteger.Zero) &&
                              !sourceValue.Equals(decimal.Zero);

                MiddleCode gotoCode = new MiddleCode(MiddleOperator.Jump);
                longList.Add(gotoCode);

                ISet <MiddleCode> trueSet  = new HashSet <MiddleCode>(),
                                  falseSet = new HashSet <MiddleCode>();
                if (isTrue)
                {
                    trueSet.Add(gotoCode);
                }
                else
                {
                    falseSet.Add(gotoCode);
                }

                targetSymbol = new Symbol(trueSet, falseSet);
            }
            else
            {
                targetSymbol = new Symbol(targetType, sourceValue);
            }

            if (targetType.IsFloating())
            {
                longList.Add(new MiddleCode(MiddleOperator.PushFloat, targetSymbol));
            }

            return(new Expression(targetSymbol, null, longList));
        }
        public static Expression Relation(MiddleOperator middleOp,
                                          Expression leftExpression,
                                          Expression rightExpression)
        {
            if (!IsConstant(leftExpression) || !IsConstant(rightExpression))
            {
                return(null);
            }

            leftExpression  = LogicalToIntegral(leftExpression);
            rightExpression = LogicalToIntegral(rightExpression);

            Type leftType  = leftExpression.Symbol.Type,
                 rightType = rightExpression.Symbol.Type;

            object leftValue  = leftExpression.Symbol.Value,
                   rightValue = rightExpression.Symbol.Value;

            int compareTo = 0;

            if (leftType.IsFloating() || rightType.IsFloating())
            {
                decimal leftDecimal, rightDecimal;

                if (leftValue is BigInteger)
                {
                    leftDecimal  = (decimal)((BigInteger)leftValue);
                    rightDecimal = (decimal)rightValue;
                }
                else if (rightValue is BigInteger)
                {
                    leftDecimal  = (decimal)leftValue;
                    rightDecimal = (decimal)((BigInteger)rightValue);
                }
                else
                {
                    leftDecimal  = (decimal)leftValue;
                    rightDecimal = (decimal)rightValue;
                }

                compareTo = leftDecimal.CompareTo(rightDecimal);
            }
            else
            {
                BigInteger leftBigInteger  = (BigInteger)leftExpression.Symbol.Value,
                           rightBigInteger = (BigInteger)rightExpression.Symbol.Value;
                compareTo = leftBigInteger.CompareTo(rightBigInteger);
            }

            bool resultValue = false;

            switch (middleOp)
            {
            case MiddleOperator.Equal:
                resultValue = (compareTo == 0);
                break;

            case MiddleOperator.NotEqual:
                resultValue = (compareTo != 0);
                break;

            case MiddleOperator.LessThan:
                resultValue = (compareTo < 0);
                break;

            case MiddleOperator.LessThanEqual:
                resultValue = (compareTo <= 0);
                break;

            case MiddleOperator.GreaterThan:
                resultValue = (compareTo > 0);
                break;

            case MiddleOperator.GreaterThanEqual:
                resultValue = (compareTo >= 0);
                break;
            }

            List <MiddleCode> longList = new List <MiddleCode>();
            MiddleCode        jumpCode = new MiddleCode(MiddleOperator.Jump);

            longList.Add(jumpCode);

            ISet <MiddleCode> jumpSet = new HashSet <MiddleCode>();

            jumpSet.Add(jumpCode);

            Symbol resultSymbol = new Symbol(null, null);

            if (resultValue)
            {
                resultSymbol.TrueSet = jumpSet;
            }
            else
            {
                resultSymbol.FalseSet = jumpSet;
            }

            return(new Expression(resultSymbol, null, longList));
        }
Exemple #22
0
        public static Expression ExplicitCast(Expression sourceExpression,
                                              Type targetType)
        {
            Expression constantExpression =
                ConstantExpression.ConstantCast(sourceExpression, targetType);

            if (constantExpression != null)
            {
                return(constantExpression);
            }

            Symbol            sourceSymbol = sourceExpression.Symbol, targetSymbol = null;
            Type              sourceType = sourceSymbol.Type;
            List <MiddleCode> shortList  = sourceExpression.ShortList,
                              longList   = sourceExpression.LongList;

            if (targetType.IsVoid())
            {
                targetSymbol = new Symbol(targetType);
            }
            else if (sourceType.IsStructOrUnion() && targetType.IsStructOrUnion())
            {
                Assert.Error(sourceType.Equals(targetType), sourceType + " to " +
                             targetType, Message.Invalid_type_cast);
                targetSymbol = new Symbol(targetType);
            }
            else if (sourceType.IsLogical() &&
                     targetType.IsIntegralPointerOrArray())
            {
                targetSymbol = new Symbol(targetType);

                Symbol     oneSymbol = new Symbol(targetType, BigInteger.One);
                MiddleCode trueCode  =
                    new MiddleCode(MiddleOperator.Assign, targetSymbol, oneSymbol);
                MiddleCodeGenerator.Backpatch(sourceSymbol.TrueSet, trueCode);
                longList.Add(trueCode);

                MiddleCode targetCode = new MiddleCode(MiddleOperator.Empty);
                longList.Add(new MiddleCode(MiddleOperator.Jump, targetCode));

                Symbol     zeroSymbol = new Symbol(targetType, BigInteger.Zero);
                MiddleCode falseCode  =
                    new MiddleCode(MiddleOperator.Assign, targetSymbol, zeroSymbol);
                MiddleCodeGenerator.Backpatch(sourceSymbol.FalseSet, falseCode);
                longList.Add(falseCode);

                longList.Add(targetCode);
            }
            else if (sourceType.IsLogical() && targetType.IsFloating())
            {
                targetSymbol = new Symbol(targetType);

                MiddleCode trueCode = new MiddleCode(MiddleOperator.PushOne);
                MiddleCodeGenerator.Backpatch(sourceSymbol.TrueSet, trueCode);
                longList.Add(trueCode);

                MiddleCode targetCode = new MiddleCode(MiddleOperator.Empty);
                longList.Add(new MiddleCode(MiddleOperator.Jump, targetCode));

                MiddleCode falseCode = new MiddleCode(MiddleOperator.PushZero);
                MiddleCodeGenerator.Backpatch(sourceSymbol.FalseSet, falseCode);
                longList.Add(falseCode);

                longList.Add(targetCode);
            }
            else if ((sourceType.IsArithmetic() || sourceType.IsPointerArrayStringOrFunction()) &&
                     targetType.IsLogical())
            {
                object zeroValue = sourceType.IsLogical() ? ((object)decimal.Zero)
                                                  : ((object)BigInteger.Zero);
                Symbol zeroSymbol = new Symbol(targetType, zeroValue);

                MiddleCode testCode =
                    new MiddleCode(MiddleOperator.NotEqual, null,
                                   sourceSymbol, zeroSymbol);
                ISet <MiddleCode> trueSet = new HashSet <MiddleCode>();
                trueSet.Add(testCode);
                longList.Add(testCode);

                MiddleCode        gotoCode = new MiddleCode(MiddleOperator.Jump);
                ISet <MiddleCode> falseSet = new HashSet <MiddleCode>();
                falseSet.Add(gotoCode);
                longList.Add(gotoCode);

                targetSymbol = new Symbol(trueSet, falseSet);
            }
            else if (sourceType.IsFloating() && targetType.IsFloating())
            {
                targetSymbol = new Symbol(targetType);
            }
            else if (sourceType.IsFloating() &&
                     targetType.IsIntegralPointerOrArray())
            {
                targetSymbol = new Symbol(targetType);

                if (targetType.Size() == 1)
                {
                    Type tempType = sourceType.IsSigned() ? Type.SignedIntegerType
                                                : Type.UnsignedIntegerType;
                    Symbol     tempSymbol = new Symbol(tempType);
                    MiddleCode tempCode   =
                        new MiddleCode(MiddleOperator.FloatingToIntegral, tempSymbol,
                                       sourceSymbol);
                    longList.Add(tempCode);
                    MiddleCode resultCode =
                        new MiddleCode(MiddleOperator.IntegralToIntegral, targetSymbol,
                                       tempSymbol);
                    longList.Add(resultCode);
                }
                else
                {
                    MiddleCode resultCode =
                        new MiddleCode(MiddleOperator.FloatingToIntegral, targetSymbol,
                                       sourceSymbol);
                    longList.Add(resultCode);
                }
            }
            else if (sourceType.IsIntegralPointerArrayStringOrFunction() &&
                     targetType.IsFloating())
            {
                targetSymbol = new Symbol(targetType);

                if (sourceType.Size() == 1)
                {
                    Type tempType = sourceType.IsSigned() ? Type.SignedIntegerType
                                                : Type.UnsignedIntegerType;
                    Symbol tempSymbol = new Symbol(tempType);
                    MiddleCodeGenerator.
                    AddMiddleCode(longList, MiddleOperator.IntegralToIntegral,
                                  tempSymbol, sourceSymbol);
                    MiddleCodeGenerator.
                    AddMiddleCode(longList, MiddleOperator.IntegralToFloating,
                                  targetSymbol, tempSymbol);
                }
                else
                {
                    MiddleCodeGenerator.
                    AddMiddleCode(longList, MiddleOperator.IntegralToFloating,
                                  targetSymbol, sourceSymbol);
                }
            }
            else if (sourceType.IsIntegralPointerArrayStringOrFunction() &&
                     targetType.IsIntegralPointerOrArray())
            {
                targetSymbol = new Symbol(targetType);
                MiddleCodeGenerator.
                AddMiddleCode(longList, MiddleOperator.IntegralToIntegral,
                              targetSymbol, sourceSymbol);
            }

            Assert.Error(targetSymbol != null, sourceType + " to " +
                         targetType, Message.Invalid_type_cast);
            return(new Expression(targetSymbol, shortList, longList));
        }