private void SetupUntypedLambdaParameters(params string[] parameterNames)
        {
            if (m_lambdaLeftExpression.IsMethodReference)
            {
                var possibleMethods = m_lambdaLeftExpression.GetMethods().ToArray();
                var methods         = new List <PrivateMethodInfoForLambdaResolver>();
                var instance        = m_lambdaLeftExpression.ExpressionCode;

                // Find methods where this parameter is a delegate that have the right number of parameters.
                foreach (var method in possibleMethods)
                {
                    bool matching         = false;
                    bool isExtension      = method.IsExtension();
                    var  parametersToSkip = (isExtension ? 1 : 0);
                    var  parameters       = method.GetParameters();
                    var  parTypes         = new List <Type>();

                    if (parameters.Length > parametersToSkip && ImplicitAttribute.IsImplicit(parameters[parametersToSkip]))
                    {
                        parametersToSkip++;   // Skip this argument because it is implicit.
                    }

                    var parameterIndex     = m_argumentIndex + parametersToSkip;
                    var resolverMethodData = new PrivateMethodInfoForLambdaResolver(method, parameterIndex);

                    if (parameterIndex < parameters.Length)
                    {
                        var parameter  = parameters[parameterIndex];
                        var targetType = parameter.ParameterType;
                        if (targetType.IsDelegate())
                        {
                            var invokeMethod     = targetType.GetMethod("Invoke");
                            var targetParameters = invokeMethod.GetParameters();
                            var returnType       = invokeMethod.ReturnType;
                            resolverMethodData.DelegateReturnType = returnType;
                            if (parameterNames.Length == targetParameters.Length)
                            {
                                matching = true;
                                if (targetType.HasGenericArguments())       // Only possible if at the same time is an extension method. (!!)
                                {
                                    var mga = method.GetGenericArguments().Select(t => new Tuple <string, Type>(t.Name, t)).ToList();
                                    resolverMethodData.MethodGenericArguments = mga;

                                    // Resolve those generic arguments from the instance.
                                    var typedArgs = instance.Type.GetTypedGenericArguments(parameters[0].ParameterType);
                                    foreach (var ti in typedArgs)
                                    {
                                        var index = mga.FindIndex(t => t.Item1 == ti.Item1);
                                        mga[index] = new Tuple <string, Type>(mga[index].Item1, ti.Item2);
                                    }

                                    // Get types of delegate input parameters.
                                    for (int i = 0; i < parameterNames.Length; i++)
                                    {
                                        var t = targetParameters[i].ParameterType;
                                        if (t.IsGenericParameter)
                                        {
                                            var index = mga.FindIndex(tt => tt.Item1 == t.Name);
                                            if (index >= 0)
                                            {
                                                t = mga[index].Item2;
                                            }
                                            else
                                            {
                                                // The type of this input parameter was not found.
                                                matching = false;
                                                break;
                                            }
                                        }
                                        parTypes.Add(t);
                                    }
                                    if (matching && returnType.IsGenericParameter)
                                    {
                                        var nUnknownTypes = mga.Count(tt => tt.Item2.IsGenericParameter);
                                        if (nUnknownTypes > 1)
                                        {
                                            matching = false;
                                        }
                                        else if (nUnknownTypes == 1)
                                        {
                                            matching = mga.Exists(tt => tt.Item2 == returnType);
                                        }
                                    }
                                    resolverMethodData.LambdaParameterTypes = parTypes;
                                }
                                else
                                {
                                    resolverMethodData.LambdaParameterTypes =
                                        parameterNames.Select((n, i) => targetParameters[i].ParameterType).ToList();
                                    resolverMethodData.DelegateType = targetType;
                                }
                            }
                        }
                    }
                    if (matching)
                    {
                        methods.Add(resolverMethodData);
                    }
                    else
                    {
                        m_lambdaLeftExpression.RemoveMethod(method);    // Remove the method as a possible match, to avoid further processing.
                    }
                }

                if (methods.Count == 1)
                {
                    var methodData = methods[0];
                    var method     = methodData.Method;

                    var scope = new ProcedureParsingScope(m_scopeStack.Peek(), "Lambda", ProcedureParsingScope.ScopeType.Lambda);
                    m_scopeStack.Push(scope);

                    for (int i = 0; i < parameterNames.Length; i++)
                    {
                        scope.AddLambdaExpressionParameter(methodData.LambdaParameterTypes[i], parameterNames[i]);
                    }

                    m_lambdaDelegateTargetType       = methodData.DelegateType;
                    m_lambdaDelegateReturnType       = methodData.DelegateReturnType;
                    m_lambdaDelegateGenericArguments = methodData.MethodGenericArguments;
                }
                else
                {
                    throw new NotImplementedException("Having more than one matching methods is not supported. Maybe it never will, and this should just be a parsing error.");
                }
            }
            else
            {
                throw new NotImplementedException();
            }
        }
        internal int CheckMethodArguments(
            ref MethodInfo method,
            bool isProcedure, bool firstParIsThis,
            Expression instance,
            Expression contextReference,
            Expression extensionInstance,
            List <SBExpressionData> arguments,
            List <SBExpressionData> suggestedAssignmentsOut,
            PropertyBlock propertyBlock = null)
        {
            ListElementPicker <SBExpressionData> argPicker = new ListElementPicker <SBExpressionData>(arguments);
            ArgumentInsertState state = ArgumentInsertState.Initial;
            bool thisParameterHandled = false;
            int  matchScore           = 1000;

            if (isProcedure)
            {
                state = ArgumentInsertState.ProcedureContext;
            }
            else if (extensionInstance != null)
            {
                state = ArgumentInsertState.ExtensionInstance;
            }

            // Construct method if generic and extension method.
            if (method.IsGenericMethodDefinition && extensionInstance != null)
            {
                // NOTE: This has to be improved with checks to avoid mistakes.
                var t = extensionInstance.Type;
                if (extensionInstance.Type.IsConstructedGenericType)
                {
                    t = t.GetGenericArguments()[0];
                }
                method = method.MakeGenericMethod(t);
            }

            var parameters = method.GetParameters();

            // Run through all the parameters; all must be assigned.
            for (int i = 0; i < parameters.Length; i++)
            {
                var p = parameters[i];
                if (state == ArgumentInsertState.ExtensionInstance)
                {
                    suggestedAssignmentsOut.Add(new SBExpressionData(extensionInstance));
                    state = ArgumentInsertState.Initial;
                    continue;
                }
                else if (state == ArgumentInsertState.ProcedureContext)
                {
                    suggestedAssignmentsOut.Add(new SBExpressionData(contextReference));
                    state = ArgumentInsertState.Initial;
                    continue;
                }
                else if (state == ArgumentInsertState.Initial)
                {
                    if (ImplicitAttribute.IsImplicit(p))
                    {
                        if (p.ParameterType.IsAssignableFrom(typeof(ICallContext)))
                        {
                            if (isProcedure)
                            {
                                suggestedAssignmentsOut.Add(new SBExpressionData(m_currentProcedure.ContextReferenceInternal));
                            }
                            else
                            {
                                suggestedAssignmentsOut.Add(new SBExpressionData(m_currentProcedure.ContextReference));
                            }
                            continue;
                        }
                        else
                        {
                            // TODO: Parsing error.
                            throw new NotImplementedException();
                        }
                    }
                    else if (!thisParameterHandled && firstParIsThis)
                    {
                        state = ArgumentInsertState.ThisReference;
                    }
                    else
                    {
                        state = ArgumentInsertState.Mandatory;
                    }
                }

                if (state != ArgumentInsertState.ThisReference)
                {
                    if (argPicker.UnpickedCount == 0 && state != ArgumentInsertState.ThisReference)
                    {
                        state = ArgumentInsertState.NoArguments;
                    }
                    else if (p.IsDefined(typeof(ParamArrayAttribute)))
                    {
                        state = ArgumentInsertState.Params;
                    }
                }

                if (state == ArgumentInsertState.Mandatory)
                {
                    if (p.GetType() == typeof(ArgumentList))
                    {
                        state = ArgumentInsertState.ArgumentList;
                    }
                    else
                    {
                        if (argPicker.Current.IsNamed)
                        {
                            if (argPicker.AllBeforeCurrentArePickedAndOthersUnpicked())
                            {
                                state = ArgumentInsertState.Named;
                            }
                            else
                            {
                                // TODO: report error; unexpected that args before current are not picked.
                                return(0);
                            }
                        }
                        else if (IsParameterAssignableFromArgument(p, argPicker.Current))
                        {
                            var a = argPicker.Pick();
                            if (p.ParameterType == typeof(object))
                            {
                                a           = a.NewExpressionCode(Expression.Convert(a.ExpressionCode, typeof(object)));
                                matchScore -= 10;    // Matching an object parameter is not as good as matching the exact same type.
                            }
                            suggestedAssignmentsOut.Add(a);
                            continue;   // next parameter
                        }
                        else if (argPicker.Current.DataType.Type == typeof(Int64) && p.ParameterType.IsPrimitiveNarrowableIntType())
                        {
                            suggestedAssignmentsOut.Add(new SBExpressionData(Expression.Convert(argPicker.Pick().ExpressionCode, p.ParameterType)));
                            continue;   // next parameter
                        }
                        else if (argPicker.Current.DataType.Type == typeof(Double) && p.ParameterType == typeof(Single))
                        {
                            suggestedAssignmentsOut.Add(new SBExpressionData(Expression.Convert(argPicker.Pick().ExpressionCode, p.ParameterType)));
                            matchScore -= 5; // Matching a 'single' is not as good as matching the exact same type.
                            continue;        // next parameter
                        }
                        else
                        {
                            state = ArgumentInsertState.Named;  // Try finding the argument by name, then.
                        }
                    }
                }

                if (state == ArgumentInsertState.ThisReference)
                {
                    thisParameterHandled = true;
                    if (p.ParameterType.IsAssignableFrom(instance.Type))
                    {
                        suggestedAssignmentsOut.Add(new SBExpressionData(instance));
                        state = ArgumentInsertState.Mandatory;  // Not sure about this...
                    }
                    else
                    {
                        return(0);   // Wrong type of 'this' reference
                    }
                }

                if (state == ArgumentInsertState.Named)
                {
                    // Note: Just because the call uses named arguments does not mean that the parameters have default values.

                    if (argPicker.FindUnpicked(a => a.ParameterName == p.Name))
                    {
                        suggestedAssignmentsOut.Add(argPicker.Pick());
                        continue;   // next parameter
                    }
                    else
                    {
                        if (p.HasDefaultValue)
                        {
                            suggestedAssignmentsOut.Add(
                                new SBExpressionData(
                                    Expression.Constant(p.DefaultValue, p.ParameterType)));
                            continue;
                        }
                        else
                        {
                            // TODO: Report argument not found, maybe
                            return(0);
                        }
                    }
                }

                if (state == ArgumentInsertState.Params)
                {
                    if (!p.ParameterType.IsArray)
                    {
                        throw new Exception("Unexpected type of 'params' parameter; not an array.");
                    }
                    var t = p.ParameterType.GetElementType();

                    if (!argPicker.AllBeforeCurrentArePickedAndOthersUnpicked())
                    {
                        // TODO: report error, maybe
                        return(0);
                    }
                    if (argPicker.UnpickedCount == 1 && p.ParameterType.IsAssignableFrom(argPicker.Current.DataType.Type))
                    {
                        suggestedAssignmentsOut.Add(argPicker.Pick());
                        continue;
                    }
                    else
                    {
                        var paramsArgs = new List <Expression>();
                        while (argPicker.UnpickedCount > 0)
                        {
                            if (t == argPicker.Current.DataType.Type)
                            {
                                paramsArgs.Add(argPicker.Pick().ExpressionCode);
                            }
                            else if (t.IsAssignableFrom(argPicker.Current.DataType.Type))
                            {
                                paramsArgs.Add(Expression.Convert(argPicker.Pick().ExpressionCode, t));
                            }
                            else
                            {
                                // TODO: report error, maybe
                                return(0);
                            }
                        }
                        suggestedAssignmentsOut.Add(new SBExpressionData(Expression.NewArrayInit(t, paramsArgs)));
                    }
                    continue;
                }

                if (state == ArgumentInsertState.NoArguments)
                {
                    if (p.IsDefined(typeof(ParamArrayAttribute)))
                    {
                        if (!p.ParameterType.IsArray)
                        {
                            throw new Exception("Unexpected type of 'params' parameter; not an array.");
                        }
                        var t = p.ParameterType.GetElementType();
                        suggestedAssignmentsOut.Add(new SBExpressionData(Expression.NewArrayInit(t)));
                    }
                    else
                    {
                        if (p.HasDefaultValue)
                        {
                            object c = p.DefaultValue;
                            if (c == null && p.ParameterType.IsValueType)
                            {
                                c = Activator.CreateInstance(p.ParameterType);
                            }
                            suggestedAssignmentsOut.Add(
                                new SBExpressionData(
                                    Expression.Constant(c, p.ParameterType)));
                            continue;
                        }
                        else
                        {
                            // TODO: Report argument not found, maybe
                            return(0);
                        }
                    }
                }
            }

            if (suggestedAssignmentsOut.Count >= parameters.Length)
            {
                if (argPicker.PickedCount < arguments.Count)
                {
                    throw new Exception("Not all passed arguments are used!");                                            // TODO: report in a better way.
                }
                return(matchScore);
            }
            return(0);
        }