Exemple #1
0
        public static ExprNode MathGetExpr(
            IParseTree ctx,
            IDictionary<ITree, ExprNode> astExprNodeMap,
            Configuration configurationInformation)
        {
            int count = 1;
            ExprNode @base = ASTExprHelper.ExprCollectSubNodes(ctx.GetChild(0), 0, astExprNodeMap)[0];

            while (true)
            {
                int token = ASTUtil.GetAssertTerminatedTokenType(ctx.GetChild(count));
                MathArithTypeEnum mathArithTypeEnum = TokenToMathEnum(token);

                ExprNode right = ASTExprHelper.ExprCollectSubNodes(ctx.GetChild(count + 1), 0, astExprNodeMap)[0];

                ExprMathNode math = new ExprMathNode(
                    mathArithTypeEnum,
                    configurationInformation.Compiler.Expression.IsIntegerDivision,
                    configurationInformation.Compiler.Expression.IsDivisionByZeroReturnsNull);
                math.AddChildNode(@base);
                math.AddChildNode(right);
                @base = math;

                count += 2;
                if (count >= ctx.ChildCount)
                {
                    break;
                }
            }

            return @base;
        }
Exemple #2
0
        private static Computer MakeDecimalComputer(
            MathArithTypeEnum operation,
            Type typeOne,
            Type typeTwo,
            bool divisionByZeroReturnsNull,
            MathContext optionalMathContext)
        {
            if (typeOne.IsDecimal() && typeTwo.IsDecimal())
            {
                if (operation == MathArithTypeEnum.DIVIDE)
                {
                    if (optionalMathContext != null)
                    {
                        return(new DivideDecimalWMathContext(divisionByZeroReturnsNull, optionalMathContext));
                    }

                    return(new DivideDecimal(divisionByZeroReturnsNull));
                }

                return(computers.Get(new MathArithDesc(typeof(decimal?), operation)));
            }

            var convertorOne = SimpleNumberCoercerFactory.GetCoercer(typeOne, typeof(decimal?));
            var convertorTwo = SimpleNumberCoercerFactory.GetCoercer(typeTwo, typeof(decimal?));

            if (operation == MathArithTypeEnum.ADD)
            {
                return(new AddDecimalConvComputer(convertorOne, convertorTwo));
            }

            if (operation == MathArithTypeEnum.SUBTRACT)
            {
                return(new SubtractDecimalConvComputer(convertorOne, convertorTwo));
            }

            if (operation == MathArithTypeEnum.MULTIPLY)
            {
                return(new MultiplyDecimalConvComputer(convertorOne, convertorTwo));
            }

            if (operation == MathArithTypeEnum.DIVIDE)
            {
                if (optionalMathContext == null)
                {
                    return(new DivideDecimalConvComputerNoMathCtx(
                               convertorOne,
                               convertorTwo,
                               divisionByZeroReturnsNull));
                }

                return(new DivideDecimalConvComputerWithMathCtx(
                           convertorOne,
                           convertorTwo,
                           divisionByZeroReturnsNull,
                           optionalMathContext));
            }

            return(new ModuloDouble());
        }
Exemple #3
0
 /// <summary>
 ///     Ctor.
 /// </summary>
 /// <param name="mathArithTypeEnum">type of math</param>
 /// <param name="isIntegerDivision">false for division returns double, true for using standard integer division</param>
 /// <param name="isDivisionByZeroReturnsNull">false for division-by-zero returns infinity, true for null</param>
 public ExprMathNode(
     MathArithTypeEnum mathArithTypeEnum,
     bool isIntegerDivision,
     bool isDivisionByZeroReturnsNull)
 {
     MathArithTypeEnum = mathArithTypeEnum;
     this._isIntegerDivision = isIntegerDivision;
     this._isDivisionByZeroReturnsNull = isDivisionByZeroReturnsNull;
 }
        public static ExprNode MakeMathNode(MathArithTypeEnum operator_, object valueLeft_, object valueRight_)
        {
            var mathNode = new ExprMathNode(operator_, false, false);

            mathNode.AddChildNode(new SupportExprNode(valueLeft_));
            mathNode.AddChildNode(new SupportExprNode(valueRight_));
            Validate3Stream(mathNode);
            return(mathNode);
        }
Exemple #5
0
        private static Computer MakeBigIntegerComputer(
            MathArithTypeEnum operation,
            Type typeOne,
            Type typeTwo)
        {
            if (typeOne.IsDecimal() && typeTwo.IsDecimal())
            {
                return(computers.Get(new MathArithDesc(typeof(decimal?), operation)));
            }

            if (typeOne.IsBigInteger() && typeTwo.IsBigInteger())
            {
                var computer = computers.Get(new MathArithDesc(typeof(BigInteger), operation));
                if (computer != null)
                {
                    return(computer);
                }
            }

            var convertorOne = SimpleNumberCoercerFactory.GetCoercerBigInteger(typeOne);
            var convertorTwo = SimpleNumberCoercerFactory.GetCoercerBigInteger(typeTwo);

            if (operation == MathArithTypeEnum.ADD)
            {
                return(new AddBigIntConvComputer(convertorOne, convertorTwo));
            }

            if (operation == MathArithTypeEnum.SUBTRACT)
            {
                return(new SubtractBigIntConvComputer(convertorOne, convertorTwo));
            }

            if (operation == MathArithTypeEnum.MULTIPLY)
            {
                return(new MultiplyBigIntConvComputer(convertorOne, convertorTwo));
            }

            if (operation == MathArithTypeEnum.DIVIDE)
            {
                return(new DivideBigIntConvComputer(convertorOne, convertorTwo));
            }

            return(new ModuloLong());
        }
        /// <summary>Returns string representation of enum.</summary>
        /// <returns>text for enum</returns>

        public static String GetExpressionText(this MathArithTypeEnum value)
        {
            switch (value)
            {
            case MathArithTypeEnum.ADD:
                return("+");

            case MathArithTypeEnum.SUBTRACT:
                return("-");

            case MathArithTypeEnum.DIVIDE:
                return("/");

            case MathArithTypeEnum.MULTIPLY:
                return("*");

            case MathArithTypeEnum.MODULO:
                return("%");
            }

            throw new ArgumentException("invalid value", "value");
        }
Exemple #7
0
 public MathArithDesc(Type type, MathArithTypeEnum arith)
 {
     _type  = type;
     _arith = arith;
 }
        /// <summary>
        /// Returns number cruncher for the target coercion type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="coercedType">target type</param>
        /// <param name="typeOne">the LHS type</param>
        /// <param name="typeTwo">the RHS type</param>
        /// <param name="isIntegerDivision">false for division returns double, true for using standard integer division</param>
        /// <param name="isDivisionByZeroReturnsNull">false for division-by-zero returns infinity, true for null</param>
        /// <param name="optionalMathContext">The optional math context.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentException">
        /// Expected base numeric type for computation result but got type  +  coercedType
        /// or
        /// Could not determine process or type  + value +  type  + coercedType
        /// or
        /// Could not determine process or type  + value +  type  + coercedType
        /// </exception>
        public static Computer GetComputer(this MathArithTypeEnum value, Type coercedType, Type typeOne, Type typeTwo, bool isIntegerDivision, bool isDivisionByZeroReturnsNull, MathContext optionalMathContext)
        {
            Type t = Nullable.GetUnderlyingType(coercedType);

            if (t != null)
            {
                coercedType = t;
            }

            if ((coercedType != typeof(BigInteger)) &&
                (coercedType != typeof(decimal)) &&
                (coercedType != typeof(double)) &&
                (coercedType != typeof(float)) &&
                (coercedType != typeof(long)) &&
                (coercedType != typeof(int)))
            {
                throw new ArgumentException("Expected base numeric type for computation result but got type " + coercedType);
            }

            if (value != MathArithTypeEnum.DIVIDE)
            {
                var key      = new MultiKeyUntyped(new Object[] { coercedType, value });
                var computer = Computers.Get(key);
                if (computer == null)
                {
                    throw new ArgumentException("Could not determine process or type " + value + " type " + coercedType);
                }
                return(computer);
            }

            if (!isIntegerDivision)
            {
                if (coercedType == typeof(decimal))
                {
                    return(isDivisionByZeroReturnsNull ? (Computer)DivideDecimalChecked : DivideDecimalUnchecked);
                }

                return(isDivisionByZeroReturnsNull ? (Computer)DivideDoubleChecked : DivideDoubleUnchecked);
            }

            if (coercedType == typeof(BigInteger))
            {
                return(DivideBigInteger);
            }
            if (coercedType == typeof(double))
            {
                return(isDivisionByZeroReturnsNull ? (Computer)DivideDoubleChecked : DivideDoubleUnchecked);
            }
            if (coercedType == typeof(float))
            {
                return(DivideSingle);
            }
            if (coercedType == typeof(long))
            {
                return(DivideInt64);
            }
            if (coercedType == typeof(int))
            {
                return(DivideInt32);
            }
            if (coercedType == typeof(decimal))
            {
                return(isDivisionByZeroReturnsNull ? (Computer)DivideDecimalChecked : DivideDecimalUnchecked);
            }

            throw new ArgumentException("Could not determine process or type " + value + " type " + coercedType);
        }
Exemple #9
0
        /// <summary>
        ///     Returns number cruncher for the target coercion type.
        /// </summary>
        /// <param name="operation">Arithmetic operation.</param>
        /// <param name="coercedType">target type</param>
        /// <param name="typeOne">the LHS type</param>
        /// <param name="typeTwo">the RHS type</param>
        /// <param name="isIntegerDivision">false for division returns double, true for using standard integer division</param>
        /// <param name="isDivisionByZeroReturnsNull">false for division-by-zero returns infinity, true for null</param>
        /// <param name="optionalMathContext">math context or null</param>
        /// <returns>number cruncher</returns>
        public static Computer GetComputer(
            MathArithTypeEnum operation,
            Type coercedType,
            Type typeOne,
            Type typeTwo,
            bool isIntegerDivision,
            bool isDivisionByZeroReturnsNull,
            MathContext optionalMathContext)
        {
            coercedType = coercedType.GetBoxedType();
            if (coercedType != typeof(double?) &&
                coercedType != typeof(float?) &&
                coercedType != typeof(long?) &&
                coercedType != typeof(int?) &&
                coercedType != typeof(decimal?) &&
                coercedType != typeof(BigInteger?) &&
                coercedType != typeof(short?) &&
                coercedType != typeof(byte))
            {
                throw new ArgumentException(
                          "Expected base numeric type for computation result but got type " + coercedType);
            }

            if (coercedType.IsDecimal())
            {
                return(MakeDecimalComputer(
                           operation,
                           typeOne,
                           typeTwo,
                           isDivisionByZeroReturnsNull,
                           optionalMathContext));
            }

            if (coercedType.IsBigInteger())
            {
                return(MakeBigIntegerComputer(
                           operation,
                           typeOne,
                           typeTwo));
            }

            if (operation != MathArithTypeEnum.DIVIDE)
            {
                var key      = new MathArithDesc(coercedType, operation);
                var computer = computers.Get(key);
                if (computer == null)
                {
                    throw new ArgumentException(
                              "Could not determine process or type " + operation + " type " + coercedType);
                }

                return(computer);
            }

            if (!isIntegerDivision)
            {
                //return new DivideDecimal(isDivisionByZeroReturnsNull);
                return(new DivideDouble(isDivisionByZeroReturnsNull));
            }

            if (coercedType == typeof(decimal?))
            {
                return(new DivideDecimal(isDivisionByZeroReturnsNull));
            }

            if (coercedType == typeof(double?))
            {
                return(new DivideDouble(isDivisionByZeroReturnsNull));
            }

            if (coercedType == typeof(float?))
            {
                return(new DivideFloat());
            }

            if (coercedType == typeof(long?))
            {
                return(new DivideLong());
            }

            if (coercedType == typeof(int?))
            {
                return(new DivideInt());
            }

            throw new ArgumentException("Could not determine process or type " + operation + " type " + coercedType);
        }