Пример #1
0
        protected static bool ConvertToFloat(ref ExpressionBase left, ref ExpressionBase right, out ExpressionBase result)
        {
            left = FloatConstantExpression.ConvertFrom(left);
            if (left.Type != ExpressionType.FloatConstant)
            {
                result = left;
                return(false);
            }

            right = FloatConstantExpression.ConvertFrom(right);
            if (right.Type != ExpressionType.FloatConstant)
            {
                result = right;
                return(false);
            }

            result = null;
            return(true);
        }
Пример #2
0
        private static bool IsMultiple(ExpressionBase left, ExpressionBase right)
        {
            var leftInteger  = left as IntegerConstantExpression;
            var rightInteger = right as IntegerConstantExpression;

            if (leftInteger != null && rightInteger != null)
            {
                return((leftInteger.Value % rightInteger.Value) == 0);
            }

            var leftFloat  = FloatConstantExpression.ConvertFrom(left) as FloatConstantExpression;
            var rightFloat = FloatConstantExpression.ConvertFrom(right) as FloatConstantExpression;

            if (leftFloat == null || rightFloat == null)
            {
                return(false);
            }

            return((leftFloat.Value % rightFloat.Value) == 0.0f);
        }
Пример #3
0
        private static bool MergeNonConstantMathematic(MathematicExpression mathematicLeft, MathematicOperation operation, ExpressionBase right, out ExpressionBase result)
        {
            var left = mathematicLeft.Right;

            result = null;

            var            newLeft      = mathematicLeft.Left;
            var            newOperation = mathematicLeft.Operation;
            ExpressionBase newRight;

            switch (mathematicLeft.Operation)
            {
            case MathematicOperation.Add:
                if (operation == MathematicOperation.Add)
                {
                    // (a + 3) + 2 => a + (3 + 2)
                    if (!MergeAddition(left, right, out newRight))
                    {
                        result = newRight;
                        return(false);
                    }
                }
                else if (operation == MathematicOperation.Subtract)
                {
                    if (IsGreater(left, right))
                    {
                        // (a + 3) - 2 => a + (3 - 2)
                        if (!MergeSubtraction(left, right, out newRight))
                        {
                            result = newRight;
                            return(false);
                        }
                    }
                    else
                    {
                        // (a + 2) - 3 => a - (3 - 2)
                        if (!MergeSubtraction(right, left, out newRight))
                        {
                            result = newRight;
                            return(false);
                        }

                        newOperation = MathematicOperation.Subtract;
                    }
                }
                else
                {
                    return(false);
                }
                break;

            case MathematicOperation.Subtract:
                if (operation == MathematicOperation.Add)
                {
                    if (IsGreater(left, right))
                    {
                        // (a - 3) + 2 => a - (3 - 2)
                        if (!MergeSubtraction(left, right, out newRight))
                        {
                            result = newRight;
                            return(false);
                        }
                    }
                    else
                    {
                        // (a - 2) + 3 => a + (3 - 2)
                        if (!MergeSubtraction(right, left, out newRight))
                        {
                            result = newRight;
                            return(false);
                        }

                        newOperation = MathematicOperation.Add;
                    }
                }
                else if (operation == MathematicOperation.Subtract)
                {
                    // (a - 3) - 2 => a - (3 + 2)
                    if (!MergeAddition(left, right, out newRight))
                    {
                        result = newRight;
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
                break;

            case MathematicOperation.Multiply:
                switch (operation)
                {
                case MathematicOperation.Multiply:
                    // (a * 3) * 2 => a * (3 * 2)
                    if (!MergeMultiplication(left, right, out newRight))
                    {
                        result = newRight;
                        return(false);
                    }
                    break;

                case MathematicOperation.Divide:
                    if (left.Type == ExpressionType.FloatConstant)
                    {
                        right = FloatConstantExpression.ConvertFrom(right);
                        if (right.Type == ExpressionType.ParseError)
                        {
                            return(false);
                        }
                    }
                    else if (right.Type == ExpressionType.FloatConstant)
                    {
                        left = FloatConstantExpression.ConvertFrom(left);
                        if (left.Type == ExpressionType.ParseError)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        // (a * 8) / 4 => a * (8 / 4) => a * 2

                        // can only merge these if the constant on the left is a multiple of the constant on the right
                        if (!IsMultiple(left, right))
                        {
                            return(false);
                        }
                    }

                    if (!MergeDivision(left, right, out newRight))
                    {
                        result = newRight;
                        return(false);
                    }
                    break;

                case MathematicOperation.Modulus:
                    // (a * 8) % 4 => a % 4
                    // can only merge these if the constant on the left is a multiple of the constant on the right
                    if (!IsMultiple(left, right))
                    {
                        return(false);
                    }

                    newRight     = right;
                    newOperation = MathematicOperation.Modulus;
                    break;

                default:
                    return(false);
                }
                break;

            case MathematicOperation.Divide:
                if (operation == MathematicOperation.Divide)
                {
                    // (a / 3) / 2 => a / (3 * 2)
                    var multiplication = new MathematicExpression(left, MathematicOperation.Multiply, right);
                    if (!MergeMultiplication(left, right, out newRight))
                    {
                        result = newRight;
                        return(false);
                    }
                }
                else if (operation == MathematicOperation.Multiply)
                {
                    if (left.Type == ExpressionType.FloatConstant || right.Type == ExpressionType.FloatConstant)
                    {
                        // (a / 3.0) * 2.0 => a * (2.0 / 3.0)
                        if (!MergeDivision(right, left, out newRight))
                        {
                            result = newRight;
                            return(false);
                        }

                        newOperation = MathematicOperation.Multiply;
                    }
                    else
                    {
                        // (a / 3) * 2 => a * (2 / 3)

                        // when integer division is performed first, the result may be floored before applying
                        // the multiplication, so don't automatically merge them.
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
                break;

            case MathematicOperation.BitwiseAnd:
                // (a & 12) & 5 => a & (12 & 5)
                if (operation != MathematicOperation.BitwiseAnd)
                {
                    return(false);
                }

                if (!MergeBitwiseAnd(left, right, out newRight))
                {
                    result = newRight;
                    return(false);
                }
                break;

            default:
                return(false);
            }

            return(MergeOperands(newLeft, newOperation, newRight, out result));
        }