/// <summary> /// Try to fit the given arguments to the underlying function. /// This function will throw an exception if the parameters can't be applied. /// The parameters that are extracted from the arguments will be returned if they can be applied successfully. /// </summary> /// <param name="info">The current call <see cref="ExecutionInformation"/>.</param> /// <param name="arguments">The arguments that are applied to this function.</param> /// <param name="returnTypes">The possible return types.</param> /// <param name="takenArguments">How many arguments could be set.</param> private object[] FitArguments(ExecutionInformation info, IReadOnlyList <ICommand> arguments, IReadOnlyList <Type> returnTypes, out int takenArguments) { var parameters = new object[CommandParameter.Length]; var filterLazy = info.GetFilterLazy(); // takenArguments: Index through arguments which have been moved into a parameter // p: Iterate through parameters takenArguments = 0; for (int p = 0; p < parameters.Length; p++) { var arg = CommandParameter[p].Type; switch (CommandParameter[p].Kind) { case ParamKind.SpecialArguments: parameters[p] = arguments; break; case ParamKind.SpecialReturns: parameters[p] = returnTypes; break; case ParamKind.Dependency: if (info.TryGet(arg, out var obj)) { parameters[p] = obj; } else if (CommandParameter[p].Optional) { parameters[p] = null; } else { throw new MissingContextCommandException($"Command '{internCommand.Name}' missing execution context '{arg.Name}'", arg); } break; case ParamKind.NormalCommand: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } parameters[p] = arguments[takenArguments]; takenArguments++; break; case ParamKind.NormalParam: case ParamKind.NormalTailString: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } var types = GetTypes(arg); if (CommandParameter[p].Kind == ParamKind.NormalTailString) { types.Insert(0, typeof(TailString)); } var argResultP = arguments[takenArguments].Execute(info, Array.Empty <ICommand>(), types); if (CommandParameter[p].Kind == ParamKind.NormalTailString && argResultP is TailString tailString) { parameters[p] = tailString.Tail; } else { parameters[p] = ConvertParam(UnwrapPrimitive(argResultP), arg, filterLazy); } takenArguments++; break; case ParamKind.NormalArray: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } var typeArr = arg.GetElementType(); var args = Array.CreateInstance(typeArr, arguments.Count - takenArguments); for (int i = 0; i < args.Length; i++, takenArguments++) { var argResultA = arguments[takenArguments].Execute(info, Array.Empty <ICommand>(), GetTypes(typeArr)); var convResult = ConvertParam(UnwrapPrimitive(argResultA), typeArr, filterLazy); args.SetValue(convResult, i); } parameters[p] = args; break; default: throw Tools.UnhandledDefault(CommandParameter[p].Kind); } } // Check if we were able to set enough arguments int wantArgumentCount = Math.Min(parameters.Length, RequiredParameters); if (takenArguments < wantArgumentCount && !returnTypes.Contains(typeof(ICommand))) { throw ThrowAtLeastNArguments(wantArgumentCount); } return(parameters); }
/// <summary> /// Try to fit the given arguments to the underlying function. /// This function will throw an exception if the parameters can't be applied. /// The parameters that are extracted from the arguments will be returned if they can be applied successfully. /// </summary> /// <param name="info">The current call <see cref="ExecutionInformation"/>.</param> /// <param name="arguments">The arguments that are applied to this function.</param> /// <param name="returnTypes">The possible return types.</param> /// <param name="takenArguments">How many arguments could be set.</param> private object[] FitArguments(ExecutionInformation info, IReadOnlyList <ICommand> arguments, IReadOnlyList <CommandResultType> returnTypes, out int takenArguments) { var parameters = new object[CommandParameter.Length]; var filterLazy = new Lazy <Algorithm.Filter>(() => info.TryGet <Algorithm.Filter>(out var filter) ? filter : Algorithm.Filter.DefaultFilter, false); // takenArguments: Index through arguments which have been moved into a parameter // p: Iterate through parameters takenArguments = 0; for (int p = 0; p < parameters.Length; p++) { var arg = CommandParameter[p].type; switch (CommandParameter[p].kind) { case ParamKind.SpecialArguments: parameters[p] = arguments; break; case ParamKind.SpecialReturns: parameters[p] = returnTypes; break; case ParamKind.Dependency: if (info.TryGet(arg, out var obj)) { parameters[p] = obj; } else if (CommandParameter[p].optional) { parameters[p] = null; } else { throw new MissingContextCommandException($"Command '{internCommand.Name}' missing execution context '{arg.Name}'", arg); } break; case ParamKind.NormalCommand: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } parameters[p] = arguments[takenArguments]; takenArguments++; break; case ParamKind.NormalParam: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } var argResultP = ((StringCommandResult)arguments[takenArguments].Execute(info, Array.Empty <ICommand>(), XCommandSystem.ReturnString)).Content; parameters[p] = ConvertParam(argResultP, arg, filterLazy.Value.Current); takenArguments++; break; case ParamKind.NormalArray: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } var typeArr = arg.GetElementType(); var args = Array.CreateInstance(typeArr, arguments.Count - takenArguments); for (int i = 0; i < args.Length; i++, takenArguments++) { var argResultA = ((StringCommandResult)arguments[takenArguments].Execute(info, Array.Empty <ICommand>(), XCommandSystem.ReturnString)).Content; var convResult = ConvertParam(argResultA, typeArr, filterLazy.Value.Current); args.SetValue(convResult, i); } parameters[p] = args; break; default: throw new ArgumentOutOfRangeException(); } } // Check if we were able to set enough arguments int wantArgumentCount = Math.Min(parameters.Length, RequiredParameters); if (takenArguments < wantArgumentCount && !returnTypes.Contains(CommandResultType.Command)) { throw ThrowAtLeastNArguments(wantArgumentCount); } return(parameters); }
/// <summary> /// Try to fit the given arguments to the underlying function. /// This function will throw an exception if the parameters can't be applied. /// The parameters that are extracted from the arguments will be returned if they can be applied successfully. /// </summary> /// <param name="info">The current call <see cref="ExecutionInformation"/>.</param> /// <param name="arguments">The arguments that are applied to this function.</param> /// <param name="returnTypes">The possible return types.</param> /// <param name="takenArguments">How many arguments could be set.</param> public R <object[], CommandException> FitArguments(ExecutionInformation info, IReadOnlyList <ICommand> arguments, IReadOnlyList <CommandResultType> returnTypes, out int takenArguments) { var parameters = new object[CommandParameter.Length]; var filterLazy = new Lazy <Algorithm.Filter>(() => info.TryGet <Algorithm.Filter>(out var filter) ? filter : Algorithm.Filter.DefaultFilter, false); // takenArguments: Index through arguments which have been moved into a parameter // p: Iterate through parameters takenArguments = 0; for (int p = 0; p < parameters.Length; p++) { var arg = CommandParameter[p].type; switch (CommandParameter[p].kind) { case ParamKind.SpecialArguments: parameters[p] = arguments; break; case ParamKind.SpecialReturns: parameters[p] = returnTypes; break; case ParamKind.Dependency: if (info.TryGet(arg, out var obj)) { parameters[p] = obj; } else if (CommandParameter[p].optional) { parameters[p] = null; } else { return(new CommandException($"Command '{internCommand.Name}' missing execution context '{arg.Name}'", CommandExceptionReason.MissingContext)); } break; case ParamKind.NormalCommand: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } parameters[p] = arguments[takenArguments]; takenArguments++; break; case ParamKind.NormalParam: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } var argResultP = ((StringCommandResult)arguments[takenArguments].Execute(info, Array.Empty <ICommand>(), XCommandSystem.ReturnString)).Content; try { parameters[p] = ConvertParam(argResultP, arg, filterLazy.Value.Current); } catch (FormatException ex) { return(new CommandException("Could not convert to " + UnwrapParamType(arg).Name, ex, CommandExceptionReason.CommandError)); } catch (OverflowException ex) { return(new CommandException("The number is too big.", ex, CommandExceptionReason.CommandError)); } takenArguments++; break; case ParamKind.NormalArray: if (takenArguments >= arguments.Count) { parameters[p] = GetDefault(arg); break; } var typeArr = arg.GetElementType(); var args = Array.CreateInstance(typeArr, arguments.Count - takenArguments); try { for (int i = 0; i < args.Length; i++, takenArguments++) { var argResultA = ((StringCommandResult)arguments[takenArguments].Execute(info, Array.Empty <ICommand>(), XCommandSystem.ReturnString)).Content; var convResult = ConvertParam(argResultA, typeArr, filterLazy.Value.Current); args.SetValue(convResult, i); } } catch (FormatException ex) { return(new CommandException("Could not convert to " + arg.Name, ex, CommandExceptionReason.CommandError)); } catch (OverflowException ex) { return(new CommandException("The number is too big.", ex, CommandExceptionReason.CommandError)); } parameters[p] = args; break; default: throw new ArgumentOutOfRangeException(); } } // Check if we were able to set enough arguments if (takenArguments < Math.Min(parameters.Length, RequiredParameters) && !returnTypes.Contains(CommandResultType.Command)) { return(new CommandException("Not enough arguments for function " + internCommand.Name, CommandExceptionReason.MissingParameter)); } return(parameters); }