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