示例#1
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
            bool found = OnValidateFunction(IgnoreCase ? function.Identifier.Name.ToLower() : function.Identifier.Name, args);

            string[][] tempVariables = null;
            // validate builtin function
            if (!found)
            {
                string functionName = function.Identifier.Name.ToLower();
                if (BuiltinFunctions.Has(functionName))
                {
                    BuiltinFunctions.Validate(functionName, function);
                    found         = true;
                    tempVariables = BuiltinFunctions.TempVariables(functionName);
                }
            }

            if (!found)
            {
                // function not found OR parameter is invalid
                throw new Exception("Function \"" + function.Identifier.Name + "\" not defined");
            }

            Result.Append(function.Identifier.Name);

            Result.Append("(");

            for (int i = 0; i < function.Expressions.Length; i++)
            {
                string[] tempVars = null;
                if (tempVariables != null && i < tempVariables.Length)
                {
                    tempVars = tempVariables[i];
                    if (tempVars != null)
                    {
                        foreach (string var in tempVars)
                        {
                            this.Parameters[var] = new RawIdentifierExpression(var);
                        }
                    }
                }
                function.Expressions[i].Accept(this);
                if (tempVars != null)
                {
                    foreach (string var in tempVars)
                    {
                        this.Parameters.Remove(var);
                    }
                }
                if (i < function.Expressions.Length - 1)
                {
                    Result.Append(",");
                }
            }

            // trim spaces before adding a closing paren
            while (Result[Result.Length - 1] == ' ')
            {
                Result.Remove(Result.Length - 1, 1);
            }

            Result.Append(")");
        }
示例#2
0
        public override void Visit(Function function)
        {
            // if raw result is preferred, display functions as it is
            if ((Options & EvaluateOptions.RawResult) == EvaluateOptions.RawResult)
            {
                throw new RawExpressionException();
            }

            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(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;
            }

            string functionName = function.Identifier.Name.ToLower();

            if (BuiltinFunctions.Has(functionName))
            {
                Result = BuiltinFunctions.ValidateAndEvaluate(functionName, function, this);
            }
            else
            {
                throw new ArgumentException("Function not found",
                                            function.Identifier.Name);
            }

            /*
             * 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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #region Round
             *  case "round":
             *
             *      CheckCase("Round", function.Identifier.Name);
             *
             *      if (!(function.Expressions.Length == 2 || function.Expressions.Length == 1))
             *          throw new ArgumentException("Round() takes 1 or 2 arguments");
             *
             *      int digits = 0;
             *      if (function.Expressions.Length == 2)
             *      {
             *          digits = Convert.ToInt16(Evaluate(function.Expressions[1]));
             *      }
             *
             *      MidpointRounding rounding = (_options & EvaluateOptions.RoundAwayFromZero) == EvaluateOptions.RoundAwayFromZero ? MidpointRounding.AwayFromZero : MidpointRounding.ToEven;
             *
             *      Result = Math.Round(Convert.ToDouble(Evaluate(function.Expressions[0])), digits, rounding);
             *
             *      break;
             *
             #endregion
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             #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
             *
             *  default:
             *      throw new ArgumentException("Function not found",
             *          function.Identifier.Name);
             * }*/
        }