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}]"); }
public override void Evaluate(TemplateContext context) { switch (Operator) { case ScriptUnaryOperator.Not: { var value = context.Evaluate(Right); context.Result = !ScriptValueConverter.ToBool(value); } break; case ScriptUnaryOperator.Negate: case ScriptUnaryOperator.Plus: { var value = context.Evaluate(Right); bool negate = Operator == ScriptUnaryOperator.Negate; var customType = value as IScriptCustomType; if (customType != null) { context.Result = customType.EvaluateUnaryExpression(this); } else if (value != null) { if (value is int) { context.Result = negate ? -((int)value) : value; } else if (value is double) { context.Result = negate ? -((double)value) : value; } else if (value is float) { context.Result = negate ? -((float)value) : value; } else if (value is long) { context.Result = negate ? -((long)value) : value; } else { throw new ScriptRuntimeException(this.Span, $"Unexpected value [{value} / Type: {value?.GetType()}]. Cannot negate(-)/positive(+) a non-numeric value"); } } } break; case ScriptUnaryOperator.FunctionAlias: context.Result = context.Evaluate(Right, true); break; case ScriptUnaryOperator.FunctionParametersExpand: // Function parameters expand is done at the function level, so here, we simply return the actual list Right?.Evaluate(context); break; default: throw new ScriptRuntimeException(Span, $"Operator [{Operator}] is not supported"); } }