public override async Task <object> Evaluate(EvaluationContext ctx)
        {
            object left = await Left.Evaluate(ctx);

            object right = await Right.Evaluate(ctx);

            // String concatenation
            if (Operator == "+" && left is string || left is char || right is string || right is char)
            {
                return(ToString(left) + ToString(right));
            }

            // Numbers
            var commonType = NumericUtil.CommonNumericType(left, right);

            if (commonType == null)
            {
                if (!NumericUtil.IsNumericType(left))
                {
                    throw new TemplateException($"Operator '{Operator}' could not be applied. Operand ({Left}) does not evaluate to a numeric value");
                }
                else if (!NumericUtil.IsNumericType(right))
                {
                    throw new TemplateException($"Operator '{Operator}' could not be applied. Operand ({Right}) does not evaluate to a numeric value");
                }
                else
                {
                    throw new Exception($"Operator '{Operator}' could not be applied"); // Developer mistake
                }
            }

            return(Operator switch
            {
                "/" => NumericUtil.Divide(left, right, commonType, Right),
                "%" => NumericUtil.Modulo(left, right, commonType, Right),
                "*" => NumericUtil.Multiply(left, right, commonType),
                "+" => NumericUtil.Add(left, right, commonType),
                "-" => NumericUtil.Subtract(left, right, commonType),
                _ => throw new Exception($"Unknown operator {Operator}"),// Future proofing
            });
Example #2
0
        public override async Task <object> Evaluate(EvaluationContext ctx)
        {
            object leftObj = await Left.Evaluate(ctx);

            object rightObj = await Right.Evaluate(ctx);

            var numericType = NumericUtil.CommonNumericType(leftObj, rightObj);

            if (numericType != null)
            {
                IComparable left  = NumericUtil.CastToNumeric(leftObj ?? 0, numericType);
                IComparable right = NumericUtil.CastToNumeric(rightObj ?? 0, numericType);

                return(Operator switch
                {
                    "=" => left.CompareTo(right) == 0,
                    "!=" => left.CompareTo(right) != 0,
                    "<>" => left.CompareTo(right) != 0,
                    "<=" => left.CompareTo(right) <= 0,
                    ">=" => left.CompareTo(right) >= 0,
                    "<" => left.CompareTo(right) < 0,
                    ">" => left.CompareTo(right) > 0,
                    _ => throw new TemplateException($"Unknown comparison operator {Operator}"),// Future proofing
                });