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; }
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()); }
/// <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); }
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"); }
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); }
/// <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); }