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 });
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 });