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);
 }
Exemplo n.º 3
0
 public override void Visit(NCalc.Domain.Function function)
 {
     ComplexExpression = true;
 }
Exemplo n.º 4
0
        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);
            }
        }