private PickyParameter[] ParametersFromContext(List <ParameterValue> context) { // Return empty if context is null. if (context == null) { return(new PickyParameter[0]); } _providedParameterCount = context.Count; // Create the parameters array with the same length as the number of input parameters. PickyParameter[] parameters = new PickyParameter[context.Count]; for (int i = 0; i < parameters.Length; i++) { // If this is the last parameter and there is a proceeding comma, set the extraneous comma range. if (i == parameters.Length - 1 && context[i].NextComma != null) { _extraneousParameterRange = context[i].NextComma.Range; } PickyParameter parameter = new PickyParameter(false); parameters[i] = parameter; if (parameter.Picky = context[i].PickyParameter != null) { // Get the picky name. parameter.Name = context[i].PickyParameter.Text; // Get the name range parameter.NameRange = context[i].PickyParameter.Range; // Check if there are any duplicate names. if (parameters.Any(p => p != null && p.Picky && p != parameter && p.Name == parameter.Name)) { // If there are, syntax error _parseInfo.Script.Diagnostics.Error($"The parameter {parameter.Name} was already set.", parameter.NameRange); } } // Set expression and expressionRange. parameter.LambdaInfo = new ExpectingLambdaInfo(); parameter.Value = _parseInfo.SetLambdaInfo(parameter.LambdaInfo).GetExpression(_getter, context[i].Expression); parameter.ExpressionRange = context[i].Expression.Range; } return(parameters); }
private OverloadMatch MatchOverload(IOverload option, PickyParameter[] inputParameters, List <ParameterValue> context) { PickyParameter lastPicky = null; // If the generics were provided ('_genericsProvided'), get the type linker from the option. OverloadMatch match = new OverloadMatch(option, _genericsProvided ? option.GetTypeLinker(_generics) : null, _parseInfo, _targetRange); match.OrderedParameters = new PickyParameter[option.Parameters.Length]; // Check type arg count. if (_genericsProvided && _generics.Length != option.TypeArgCount) { match.IncorrectTypeArgCount(_parseInfo.TranslateInfo, _targetRange); } // Iterate through the option's parameters. for (int i = 0; i < inputParameters.Length; i++) { // Out of range if (i >= option.Parameters.Length) { if (i == option.Parameters.Length) { match.Error(string.Format(_errorMessages.BadParameterCount, inputParameters.Length), _targetRange); } continue; } // Non-picky else if (inputParameters[i].ParameterOrdered(option.Parameters[i])) { // If the picky parameters end but there is an additional picky parameter, throw a syntax error. if (lastPicky != null && inputParameters[i].Name == null) { match.Error($"Named argument '{lastPicky.Name}' is used out-of-position but is followed by an unnamed argument", lastPicky.NameRange); } else { match.OrderedParameters[i] = inputParameters[i]; // If _genericsFilled is false, get context-inferred type arguments. if (!_genericsProvided) { ExtractInferredGenerics(match, option.Parameters[i].GetCodeType(_parseInfo.TranslateInfo), inputParameters[i].Value.Type()); } // Next contextual parameter if (i == inputParameters.Length - 1 && i < option.Parameters.Length - 1) { match.LastContextualParameterIndex = i + 1; } } } else // Picky { // Picky parameter ends. lastPicky = inputParameters[i]; // Set relevant picky parameter. bool nameFound = false; for (int p = 0; p < option.Parameters.Length && !nameFound; p++) { if (inputParameters[i].Name == option.Parameters[p].Name) { // A matching parameter was found. match.OrderedParameters[p] = inputParameters[i]; nameFound = true; // If _genericsFilled is false, get context-inferred type arguments. if (!_genericsProvided) { ExtractInferredGenerics(match, option.Parameters[p].GetCodeType(_parseInfo.TranslateInfo), inputParameters[i].Value.Type()); } } } // If the named argument's name is not found, throw an error. if (!nameFound) { match.Error($"Named argument '{lastPicky.Name}' does not exist in the function '{option.GetLabel(_parseInfo.TranslateInfo, LabelInfo.OverloadError)}'.", inputParameters[i].NameRange); } } } // Compare parameter types. match.UpdateAllParameters(); // Make sure every type arg was accounted for. if (!_genericsProvided && !match.TypeArgLinkerCompleted) { match.InferSuccessful = false; } // Get the missing parameters. match.GetMissingParameters(_errorMessages, context, _targetRange, CallRange); return(match); }