Example #1
0
        public IParseTreeValue Evaluate(IParseTreeValue LHS, IParseTreeValue RHS, string opSymbol)
        {
            if (!(IsSupportedSymbol(opSymbol)))
            {
                throw new ArgumentException($"Unsupported operation ({opSymbol}) passed to Evaluate function");
            }

            if (opSymbol.Equals(LogicalOperators.NOT))
            {
                throw new ArgumentException($"Unary operator ({opSymbol}) passed to binary Evaluate function");
            }

            var opProvider = new OperatorTypesProvider((LHS.ValueType, RHS.ValueType), opSymbol);

            if (opProvider.IsMismatch)
            {
                return(_valueFactory.CreateMismatchExpression($"{LHS.Token} {opSymbol} {RHS.Token}", Tokens.Variant));
            }

            if (ArithmeticOperators.Includes(opSymbol))
            {
                return(EvaluateArithmeticOp(opSymbol, LHS, RHS));
            }

            if (RelationalOperators.Includes(opSymbol))
            {
                return(EvaluateRelationalOp(opSymbol, LHS, RHS));
            }

            return(EvaluateLogicalOperator(opSymbol, LHS, RHS));
        }
Example #2
0
 private bool IsSupportedSymbol(string opSymbol)
 {
     return(ArithmeticOperators.Includes(opSymbol) ||
            RelationalOperators.Includes(opSymbol) ||
            LogicalOperators.Incudes(opSymbol));
 }
Example #3
0
        private IParseTreeValue EvaluateArithmeticOp(string opSymbol, IParseTreeValue LHS, IParseTreeValue RHS)
        {
            Debug.Assert(ArithmeticOperators.Includes(opSymbol));

            var opProvider = new OperatorTypesProvider((LHS.ValueType, RHS.ValueType), opSymbol);

            if (!(LHS.ParsesToConstantValue && RHS.ParsesToConstantValue))
            {
                //Unable to resolve to a value, return an expression
                return(_valueFactory.CreateExpression($"{LHS.Token} {opSymbol} {RHS.Token}", opProvider.OperatorDeclaredType));
            }

            if (!LHS.TryLetCoerce(opProvider.OperatorEffectiveType, out var effLHS) ||
                !RHS.TryLetCoerce(opProvider.OperatorEffectiveType, out var effRHS))
            {
                return(_valueFactory.CreateExpression($"{LHS.Token} {opSymbol} {RHS.Token}", opProvider.OperatorDeclaredType));
            }

            if (opProvider.OperatorEffectiveType.Equals(Tokens.Date))
            {
                if (!(LHS.TryLetCoerce(Tokens.Double, out effLHS) && RHS.TryLetCoerce(Tokens.Double, out effRHS)))
                {
                    return(_valueFactory.CreateExpression($"{LHS.Token} {opSymbol} {RHS.Token}", opProvider.OperatorEffectiveType));
                }
            }

            if (opSymbol.Equals(ArithmeticOperators.MULTIPLY))
            {
                return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a * b, (double a, double b) => a * b), opProvider.OperatorDeclaredType));
            }
            if (opSymbol.Equals(ArithmeticOperators.DIVIDE))
            {
                return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a / b, (double a, double b) => a / b), opProvider.OperatorDeclaredType));
            }
            if (opSymbol.Equals(ArithmeticOperators.INTEGER_DIVIDE))
            {
                return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, IntDivision, IntDivision), opProvider.OperatorDeclaredType));
            }
            if (opSymbol.Equals(ArithmeticOperators.PLUS))
            {
                if (opProvider.OperatorEffectiveType.Equals(Tokens.String))
                {
                    return(_valueFactory.CreateValueType(Concatenate(LHS, RHS), opProvider.OperatorDeclaredType));
                }
                if (opProvider.OperatorEffectiveType.Equals(Tokens.Date))
                {
                    var result = _valueFactory.CreateDeclaredType(Calculate(effLHS, effRHS, null, (double a, double b) => a + b), Tokens.Double);
                    return(_valueFactory.CreateDate(result.AsDouble()));
                }
                return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a + b, (double a, double b) => a + b), opProvider.OperatorDeclaredType));
            }
            if (opSymbol.Equals(ArithmeticOperators.MINUS))
            {
                if (LHS.ValueType.Equals(Tokens.Date) && RHS.ValueType.Equals(Tokens.Date))
                {
                    return(_valueFactory.CreateDate(LHS.AsDouble() - RHS.AsDouble()));
                }
                return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a - b, (double a, double b) => a - b), opProvider.OperatorDeclaredType));
            }
            if (opSymbol.Equals(ArithmeticOperators.EXPONENT))
            {
                //Math.Pow only takes doubles, so the decimal conversion option is null
                return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, null, Math.Pow), opProvider.OperatorDeclaredType));
            }
            if (opSymbol.Equals(ArithmeticOperators.MODULO))
            {
                return(_valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a % b, (double a, double b) => a % b), opProvider.OperatorDeclaredType));
            }

            //ArithmeticOperators.AMPERSAND
            return(_valueFactory.CreateValueType(Concatenate(LHS, RHS), opProvider.OperatorDeclaredType));
        }