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); }
/// <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 }