public override void Visit(Function function) { foreach (var expression in function.Expressions) expression.Accept(this); }
public override void Visit(Function function) { Methods.Add(function.Identifier.Name); foreach (var rule in function.Expressions) rule.Accept(this); }
public override void Visit(NCalc.Domain.Function function) { ComplexExpression = true; }
public override void Visit(Function 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 (int 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(options.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()) { #region Abs case "abs": CheckCase("Abs", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Abs() takes exactly 1 argument"); } Result = Math.Abs(Convert.ToDecimal( Evaluate(function.Expressions[0])) ); break; #endregion Abs #region Acos case "acos": CheckCase("Acos", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Acos() takes exactly 1 argument"); } Result = Math.Acos(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Acos #region Asin case "asin": CheckCase("Asin", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Asin() takes exactly 1 argument"); } Result = Math.Asin(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Asin #region Atan case "atan": CheckCase("Atan", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Atan() takes exactly 1 argument"); } Result = Math.Atan(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Atan #region Ceiling case "ceiling": CheckCase("Ceiling", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Ceiling() takes exactly 1 argument"); } Result = Math.Ceiling(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Ceiling #region Cos case "cos": CheckCase("Cos", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Cos() takes exactly 1 argument"); } Result = Math.Cos(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Cos #region Exp case "exp": CheckCase("Exp", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Exp() takes exactly 1 argument"); } Result = Math.Exp(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Exp #region Floor case "floor": CheckCase("Floor", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Floor() takes exactly 1 argument"); } Result = Math.Floor(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Floor #region IEEERemainder case "ieeeremainder": CheckCase("IEEERemainder", function.Identifier.Name); if (function.Expressions.Length != 2) { throw new ArgumentException("IEEERemainder() takes exactly 2 arguments"); } Result = Math.IEEERemainder(Convert.ToDouble(Evaluate(function.Expressions[0])), Convert.ToDouble(Evaluate(function.Expressions[1]))); break; #endregion IEEERemainder #region Log case "log": CheckCase("Log", function.Identifier.Name); if (function.Expressions.Length != 2) { throw new ArgumentException("Log() takes exactly 2 arguments"); } Result = Math.Log(Convert.ToDouble(Evaluate(function.Expressions[0])), Convert.ToDouble(Evaluate(function.Expressions[1]))); break; #endregion Log #region Log10 case "log10": CheckCase("Log10", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Log10() takes exactly 1 argument"); } Result = Math.Log10(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Log10 #region Pow case "pow": CheckCase("Pow", function.Identifier.Name); if (function.Expressions.Length != 2) { throw new ArgumentException("Pow() takes exactly 2 arguments"); } Result = Math.Pow(Convert.ToDouble(Evaluate(function.Expressions[0])), Convert.ToDouble(Evaluate(function.Expressions[1]))); break; #endregion Pow #region Round case "round": CheckCase("Round", function.Identifier.Name); if (function.Expressions.Length != 2) { throw new ArgumentException("Round() takes exactly 2 arguments"); } MidpointRounding rounding = options.RoundAwayFromZero() ? MidpointRounding.AwayFromZero : MidpointRounding.ToEven; Result = Math.Round(Convert.ToDouble(Evaluate(function.Expressions[0])), Convert.ToInt16(Evaluate(function.Expressions[1])), rounding); break; #endregion Round #region Sign case "sign": CheckCase("Sign", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Sign() takes exactly 1 argument"); } Result = Math.Sign(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Sign #region Sin case "sin": CheckCase("Sin", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Sin() takes exactly 1 argument"); } Result = Math.Sin(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Sin #region Sqrt case "sqrt": CheckCase("Sqrt", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Sqrt() takes exactly 1 argument"); } Result = Math.Sqrt(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Sqrt #region Tan case "tan": CheckCase("Tan", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Tan() takes exactly 1 argument"); } Result = Math.Tan(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Tan #region Truncate case "truncate": CheckCase("Truncate", function.Identifier.Name); if (function.Expressions.Length != 1) { throw new ArgumentException("Truncate() takes exactly 1 argument"); } Result = Math.Truncate(Convert.ToDouble(Evaluate(function.Expressions[0]))); break; #endregion Truncate #region Max case "max": CheckCase("Max", function.Identifier.Name); if (function.Expressions.Length != 2) { throw new ArgumentException("Max() takes exactly 2 arguments"); } object maxleft = Evaluate(function.Expressions[0]); object maxright = Evaluate(function.Expressions[1]); Result = Numbers.Max(maxleft, maxright); break; #endregion Max #region Min case "min": CheckCase("Min", function.Identifier.Name); if (function.Expressions.Length != 2) { throw new ArgumentException("Min() takes exactly 2 arguments"); } object minleft = Evaluate(function.Expressions[0]); object minright = Evaluate(function.Expressions[1]); Result = Numbers.Min(minleft, minright); break; #endregion Min #region if case "if": CheckCase("if", function.Identifier.Name); if (function.Expressions.Length != 3) { throw new ArgumentException("if() takes exactly 3 arguments"); } bool cond = Convert.ToBoolean(Evaluate(function.Expressions[0])); Result = cond ? Evaluate(function.Expressions[1]) : Evaluate(function.Expressions[2]); break; #endregion if #region in case "in": CheckCase("in", function.Identifier.Name); if (function.Expressions.Length < 2) { throw new ArgumentException("in() takes at least 2 arguments"); } object parameter = Evaluate(function.Expressions[0]); bool evaluation = false; // Goes through any values, and stop whe one is found for (int i = 1; i < function.Expressions.Length; i++) { object argument = Evaluate(function.Expressions[i]); if (CompareUsingMostPreciseType(parameter, argument) == 0) { evaluation = true; break; } } Result = evaluation; break; #endregion in default: throw new ArgumentException("Function not found", function.Identifier.Name); } }