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