/// <summary>
        /// Creates a <see cref="ForCSharpStatement"/> that represents a for loop.
        /// </summary>
        /// <param name="initializers">The loop initializers.</param>
        /// <param name="test">The condition of the loop.</param>
        /// <param name="iterators">The loop iterators.</param>
        /// <param name="body">The body of the loop.</param>
        /// <param name="break">The break target used by the loop body.</param>
        /// <param name="continue">The continue target used by the loop body.</param>
        /// <returns>The created <see cref="ForCSharpStatement"/>.</returns>
        public static ForCSharpStatement For(IEnumerable <BinaryExpression> initializers, Expression test, IEnumerable <Expression> iterators, Expression body, LabelTarget @break, LabelTarget @continue)
        {
            ValidateLoop(test, body, @break, @continue, optionalTest: true);

            // NB: While C# requires all initializers to be of the same type, we don't quite need that restriction here.
            //     This can be revisited. We will check whether all initializers are simple assignments though.

            var initializerList = initializers.ToReadOnly <Expression>();
            var uniqueVariables = new HashSet <ParameterExpression>();
            var variables       = new List <ParameterExpression>();

            foreach (BinaryExpression initializer in initializerList)
            {
                if (initializer.NodeType != ExpressionType.Assign || initializer.Left.NodeType != ExpressionType.Parameter)
                {
                    throw Error.InvalidInitializer();
                }

                var variable = (ParameterExpression)initializer.Left;

                if (!uniqueVariables.Add(variable))
                {
                    throw LinqError.DuplicateVariable(variable);
                }

                // NB: We keep them in the order specified and don't rely on the hash set.
                variables.Add(variable);
            }

            var variableList = variables.ToReadOnly();

            var iteratorList = iterators.ToReadOnly();

            return(ForCSharpStatement.Make(variableList, initializerList, test, iteratorList, body, @break, @continue));
        }
        /// <summary>
        /// Creates a <see cref="ForCSharpStatement"/> that represents a for loop.
        /// </summary>
        /// <param name="variables">The variables in scope of the loop.</param>
        /// <param name="initializers">The loop initializers.</param>
        /// <param name="test">The condition of the loop.</param>
        /// <param name="iterators">The loop iterators.</param>
        /// <param name="body">The body of the loop.</param>
        /// <param name="break">The break target used by the loop body.</param>
        /// <param name="continue">The continue target used by the loop body.</param>
        /// <returns>The created <see cref="ForCSharpStatement"/>.</returns>
        public static ForCSharpStatement For(IEnumerable <ParameterExpression> variables, IEnumerable <Expression> initializers, Expression test, IEnumerable <Expression> iterators, Expression body, LabelTarget @break, LabelTarget @continue)
        {
            ValidateLoop(test, body, @break, @continue, optionalTest: true);

            // NB: While C# requires all initializers to be of the same type, we don't quite need that restriction here.
            //     This can be revisited. We will check whether all initializers are simple assignments though.

            var variableList = variables.ToReadOnly();

            var initializerList = initializers.ToReadOnly <Expression>();

            RequiresNotNullItems(initializerList, nameof(initializers));

            var uniqueVariables = new HashSet <ParameterExpression>();

            foreach (var variable in variableList)
            {
                if (!uniqueVariables.Add(variable))
                {
                    throw LinqError.DuplicateVariable(variable);
                }
            }

            var iteratorList = iterators.ToReadOnly();

            RequiresNotNullItems(iteratorList, nameof(iterators));

            return(ForCSharpStatement.Make(variableList, initializerList, test, iteratorList, body, @break, @continue));
        }
        /// <summary>
        /// Creates a <see cref="ForCSharpStatement"/> that represents a for loop.
        /// </summary>
        /// <param name="variables">The variables in scope of the loop.</param>
        /// <param name="initializers">The loop initializers.</param>
        /// <param name="test">The condition of the loop.</param>
        /// <param name="iterators">The loop iterators.</param>
        /// <param name="body">The body of the loop.</param>
        /// <param name="break">The break target used by the loop body.</param>
        /// <param name="continue">The continue target used by the loop body.</param>
        /// <param name="locals">The variables that are in scope of the loop.</param>
        /// <returns>The created <see cref="ForCSharpStatement"/>.</returns>
        public static ForCSharpStatement For(IEnumerable <ParameterExpression> variables, IEnumerable <Expression> initializers, Expression test, IEnumerable <Expression> iterators, Expression body, LabelTarget @break, LabelTarget @continue, IEnumerable <ParameterExpression> locals)
        {
            ValidateLoop(test, body, @break, @continue, optionalTest: true);

            // NB: While C# requires all initializers to be of the same type, we don't quite need that restriction here.
            //     This can be revisited. We will check whether all initializers are simple assignments though.

            var variableList = CheckUniqueVariables(variables, nameof(variables));

            var initializerList = initializers.ToReadOnly();

            RequiresNotNullItems(initializerList, nameof(initializers));

            var iteratorList = iterators.ToReadOnly();

            RequiresNotNullItems(iteratorList, nameof(iterators));

            var localsList = CheckUniqueVariables(locals, nameof(locals));

            return(ForCSharpStatement.Make(variableList, initializerList, test, iteratorList, body, @break, @continue, localsList));
        }