Value Execute()
        {
            var args       = _arguments.Length;
            var difference = int.MaxValue;
            var expected   = 0;
            YAMPRuntimeException exception = null;

            foreach (var kv in _functions)
            {
                var key = kv.Key;

                if (args < key.MinimumArguments || args > key.MaximumArguments)
                {
                    var diff = Math.Min(Math.Abs(key.MinimumArguments - args), Math.Abs(args - key.MaximumArguments));

                    if (diff < difference)
                    {
                        difference = diff;
                        expected   = args < key.MinimumArguments ? key.MinimumArguments : key.MaximumArguments;
                    }

                    continue;
                }

                var f = kv.Value;
                exception = BuildArguments(key);

                if (exception == null)
                {
                    try
                    {
                        return(f.Invoke(this, _arguments) as Value);
                    }
                    catch (Exception ex)
                    {
                        if (ex.InnerException != null)
                        {
                            throw ex.InnerException;
                        }

                        throw;
                    }
                }
            }

            if (exception != null)
            {
                throw exception;
            }

            throw new YAMPArgumentNumberException(Name, args, expected);
        }
Esempio n. 2
0
        /// <summary>
        /// Performs the function execution.
        /// </summary>
        /// <param name="argument">The argument(s) (if presented in an "ArgumentValue").</param>
        /// <returns>The evaluated value.</returns>
        public override Value Perform(Value argument)
        {
            if (argument is ArgumentsValue)
            {
                arguments = (argument as ArgumentsValue).Values;
            }
            else
            {
                arguments = new Value[] { argument }
            };

            return(Execute());
        }

        #endregion

        #region Helpers

        Value Execute()
        {
            var args       = arguments.Length;
            var difference = int.MaxValue;
            var expected   = 0;
            YAMPRuntimeException exception = null;

            foreach (var kv in functions)
            {
                var key = kv.Key;

                if (args < key.MinimumArguments || args > key.MaximumArguments)
                {
                    var diff = Math.Min(Math.Abs(key.MinimumArguments - args), Math.Abs(args - key.MaximumArguments));

                    if (diff < difference)
                    {
                        difference = diff;
                        expected   = args < key.MinimumArguments ? key.MinimumArguments : key.MaximumArguments;
                    }

                    continue;
                }

                var f = kv.Value;
                exception = BuildArguments(key);

                if (exception == null)
                {
                    try
                    {
                        return(f.Invoke(this, arguments) as Value);
                    }
                    catch (Exception ex)
                    {
                        if (ex.InnerException != null)
                        {
                            throw ex.InnerException;
                        }

                        throw;
                    }
                }
            }

            if (exception != null)
            {
                throw exception;
            }

            throw new YAMPArgumentNumberException(Name, args, expected);
        }

        YAMPRuntimeException BuildArguments(FunctionParameters yp)
        {
            var attrs  = yp.OptionalArguments;
            var values = new List <Value>();

            for (var i = 0; i < arguments.Length; i++)
            {
                var opt = false;

                for (var j = 0; j < attrs.Length; j++)
                {
                    var attr = attrs[j];

                    if (attr.Index == i)
                    {
                        var rest = arguments.Length - i;

                        if (rest >= attr.MinimumArguments)
                        {
                            var av = new ArgumentsValue();
                            var pt = Math.Min(attr.MaximumArguments / attr.StepArguments, rest / attr.StepArguments);

                            for (var k = 0; k < pt; k++)
                            {
                                for (var l = 0; l < attr.StepArguments; l++)
                                {
                                    av.Insert(arguments[i++]);
                                }
                            }

                            values.Add(av);
                            opt = true;
                        }
                    }
                }

                if (!opt)
                {
                    var idx = values.Count;

                    if (!yp.ParameterTypes[idx].IsInstanceOfType(arguments[idx]))
                    {
                        return(new YAMPArgumentInvalidException(Name, arguments[idx].Header, yp.ParameterTypes[idx].Name.RemoveValueConvention(), idx));
                    }

                    values.Add(arguments[i]);
                }
            }

            while (values.Count < yp.ParameterTypes.Length)
            {
                values.Add(new ArgumentsValue());
            }

            arguments = values.ToArray();
            return(null);
        }

        #endregion
    }