private void CheckCase(FunctionExpression function, string reference) { var called = function.Identifier.Name; if (IgnoreCase) { if (string.Equals(called, reference, StringComparison.InvariantCultureIgnoreCase)) { return; } throw new ArgumentException("Function not found.", called); } if (called != reference) { throw new ArgumentException($"Function not found: '{called}'. Try '{reference}' instead."); } }
public override void Visit(FunctionExpression function) { var args = new FunctionArgs { Parameters = new Expression[function.Expressions.Length] }; // Don't call parameters right now, instead let the function do it as needed. // Some parameters shouldn't be called, for instance, in a if(), the "not" value might be a division by zero // Evaluating every value could produce unexpected behaviour for (var i = 0; i < function.Expressions.Length; i++) { args.Parameters[i] = new Expression(function.Expressions[i], options); args.Parameters[i].EvaluateFunction += EvaluateFunction; args.Parameters[i].EvaluateParameter += EvaluateParameter; // Assign the parameters of the Expression to the arguments so that custom Functions and Parameters can use them args.Parameters[i].Parameters = Parameters; } // Calls external implementation OnEvaluateFunction(IgnoreCase ? function.Identifier.Name.ToLower() : function.Identifier.Name, args); // If an external implementation was found get the result back if (args.HasResult) { Result = args.Result; return; } switch (function.Identifier.Name.ToLower(CultureInfo.InvariantCulture)) { case "abs": CheckCase(function, "Abs"); CheckExactArgumentCount(function, 1); Result = Mathf.Abs(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "acos": CheckCase(function, "Acos"); CheckExactArgumentCount(function, 1); Result = Mathf.Acos(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "asin": CheckCase(function, "Asin"); CheckExactArgumentCount(function, 1); Result = Mathf.Asin(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "atan": CheckCase(function, "Atan"); CheckExactArgumentCount(function, 1); Result = Mathf.Atan(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "ceil": CheckCase(function, "Ceil"); CheckExactArgumentCount(function, 1); Result = Mathf.Ceil(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "cos": CheckCase(function, "Cos"); CheckExactArgumentCount(function, 1); Result = Mathf.Cos(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "exp": CheckCase(function, "Exp"); CheckExactArgumentCount(function, 1); Result = Mathf.Exp(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "floor": CheckCase(function, "Floor"); CheckExactArgumentCount(function, 1); Result = Mathf.Floor(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "log": CheckCase(function, "Log"); CheckExactArgumentCount(function, 2); Result = Mathf.Log(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0])), ConversionUtility.Convert <float>(Evaluate(function.Expressions[1]))); break; case "log10": CheckCase(function, "Log10"); CheckExactArgumentCount(function, 1); Result = Mathf.Log10(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "pow": CheckCase(function, "Pow"); CheckExactArgumentCount(function, 2); Result = Mathf.Pow(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0])), ConversionUtility.Convert <float>(Evaluate(function.Expressions[1]))); break; case "round": CheckCase(function, "Round"); CheckExactArgumentCount(function, 1); //var rounding = (options & EvaluateOptions.RoundAwayFromZero) == EvaluateOptions.RoundAwayFromZero ? MidpointRounding.AwayFromZero : MidpointRounding.ToEven; Result = Mathf.Round(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "sign": CheckCase(function, "Sign"); CheckExactArgumentCount(function, 1); Result = Mathf.Sign(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "sin": CheckCase(function, "Sin"); CheckExactArgumentCount(function, 1); Result = Mathf.Sin(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "sqrt": CheckCase(function, "Sqrt"); CheckExactArgumentCount(function, 1); Result = Mathf.Sqrt(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "tan": CheckCase(function, "Tan"); CheckExactArgumentCount(function, 1); Result = Mathf.Tan(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0]))); break; case "max": CheckCase(function, "Max"); CheckExactArgumentCount(function, 2); Result = Mathf.Max(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0])), ConversionUtility.Convert <float>(Evaluate(function.Expressions[1]))); break; case "min": CheckCase(function, "Min"); CheckExactArgumentCount(function, 2); Result = Mathf.Min(ConversionUtility.Convert <float>(Evaluate(function.Expressions[0])), ConversionUtility.Convert <float>(Evaluate(function.Expressions[1]))); break; case "in": CheckCase(function, "In"); CheckExactArgumentCount(function, 2); var parameter = Evaluate(function.Expressions[0]); var evaluation = false; // Goes through any values, and stop whe one is found for (var i = 1; i < function.Expressions.Length; i++) { var argument = Evaluate(function.Expressions[i]); if (Equals(parameter, argument)) { evaluation = true; break; } } Result = evaluation; break; default: throw new ArgumentException("Function not found", function.Identifier.Name); } }