Scriban.Runtime.ScriptBinaryExpression.Evaluate C# (CSharp) Method

Evaluate() public method

public Evaluate ( TemplateContext context ) : void
context TemplateContext
return void
        public override void Evaluate(TemplateContext context)
        {
            var leftValueOriginal = context.Evaluate(Left);
            var leftValue = leftValueOriginal;
            var rightValueOriginal = context.Evaluate(Right);
            object rightValue = rightValueOriginal;

            if (Operator == ScriptBinaryOperator.EmptyCoalescing)
            {
                context.Result = leftValue ?? rightValue;
                return;
            }
            else if (Operator == ScriptBinaryOperator.And || Operator == ScriptBinaryOperator.Or)
            {
                var leftBoolValue = ScriptValueConverter.ToBool(leftValue);
                var rightBoolValue = ScriptValueConverter.ToBool(rightValue);
                if (Operator == ScriptBinaryOperator.And)
                {
                    context.Result = leftBoolValue && rightBoolValue;
                }
                else
                {
                    context.Result = leftBoolValue || rightBoolValue;
                }

                return;
            }
            else
            {
                switch (Operator)
                {
                    case ScriptBinaryOperator.ShiftLeft:
                    case ScriptBinaryOperator.ShiftRight:
                        if (leftValue is IList || rightValue is IList)
                        {
                            // Special path for IList to allow custom binary expression
                            context.Result = ScriptArray.CustomOperator.EvaluateBinaryExpression(this, leftValue,
                                rightValue);
                            return;
                        }
                        break;
                    case ScriptBinaryOperator.CompareEqual:
                    case ScriptBinaryOperator.CompareNotEqual:
                    case ScriptBinaryOperator.CompareGreater:
                    case ScriptBinaryOperator.CompareLess:
                    case ScriptBinaryOperator.CompareGreaterOrEqual:
                    case ScriptBinaryOperator.CompareLessOrEqual:
                    case ScriptBinaryOperator.Add:
                    case ScriptBinaryOperator.Substract:
                    case ScriptBinaryOperator.Multiply:
                    case ScriptBinaryOperator.Divide:
                    case ScriptBinaryOperator.DivideRound:
                    case ScriptBinaryOperator.Modulus:
                    case ScriptBinaryOperator.RangeInclude:
                    case ScriptBinaryOperator.RangeExclude:
                        var leftType = leftValue?.GetType();
                        var rightType = rightValue?.GetType();

                        if (leftValue is string || rightValue is string)
                        {
                            context.Result = CalculateToString(Operator, leftValue, rightValue);
                            {
                                // TODO: Log an error if CalculateToString return null?
                                //context.LogError(Span, $"Operation [{Operator}] on strings not supported");
                            }
                        }
                        else
                        {
                            context.Result = Calculate(Operator, leftValue, leftType, rightValue, rightType);
                        }
                        return;
                }
            }

            throw new ScriptRuntimeException(Span, $"Operator [{Operator.ToText()}] is not implemented for the left [{Left}] / right [{Right}]");
        }

Usage Example

Example #1
0
        private static bool CompareTo(TemplateContext context, SourceSpan span, ScriptBinaryOperator op, IEnumerable <object> left, IEnumerable <object> right)
        {
            // Compare the length first
            var leftCount  = left.Count();
            var rightCount = right.Count();
            var compare    = leftCount.CompareTo(rightCount);

            switch (op)
            {
            case ScriptBinaryOperator.CompareEqual:
                if (compare != 0)
                {
                    return(false);
                }
                break;

            case ScriptBinaryOperator.CompareNotEqual:
                if (compare != 0)
                {
                    return(true);
                }
                if (leftCount == 0)
                {
                    return(false);
                }
                break;

            case ScriptBinaryOperator.CompareLessOrEqual:
            case ScriptBinaryOperator.CompareLess:
                if (compare < 0)
                {
                    return(true);
                }
                if (compare > 0)
                {
                    return(false);
                }
                if (leftCount == 0 && op == ScriptBinaryOperator.CompareLess)
                {
                    return(false);
                }
                break;

            case ScriptBinaryOperator.CompareGreaterOrEqual:
            case ScriptBinaryOperator.CompareGreater:
                if (compare < 0)
                {
                    return(false);
                }
                if (compare > 0)
                {
                    return(true);
                }
                if (leftCount == 0 && op == ScriptBinaryOperator.CompareGreater)
                {
                    return(false);
                }
                break;

            default:
                throw new ScriptRuntimeException(span, $"The operator `{op.ToText()}` is not supported between {context.GetTypeName(left)} and {context.GetTypeName(right)}.");
            }

            // Otherwise we need to compare each element

            var leftIterator  = left.GetEnumerator();
            var rightIterator = right.GetEnumerator();

            while (leftIterator.MoveNext() && rightIterator.MoveNext())
            {
                var leftValue  = leftIterator.Current;
                var rightValue = rightIterator.Current;
                var result     = (bool)ScriptBinaryExpression.Evaluate(context, span, op, leftValue, rightValue);
                if (!result)
                {
                    return(false);
                }
            }

            return(true);
        }