private Node Visit(ForEachStatement forEachStatement) { if (expandForEachStatements) { // run analysis on collection Visit(forEachStatement.Collection); var inference = forEachStatement.Collection.TypeInference.Declaration as Variable; if (!(inference != null && inference.Type is ArrayType)) return forEachStatement; if ((inference.Type as ArrayType).Dimensions.Count > 1) { Error(ParadoxMessageCode.ErrorMultiDimArray, forEachStatement.Span, inference, forEachStatement, analyzedModuleMixin.MixinName); return forEachStatement; } var dim = (int)((inference.Type as ArrayType).Dimensions.FirstOrDefault() as LiteralExpression).Value; var result = new StatementList(); for (int i = 0; i < dim; ++i) { var cloned = forEachStatement.DeepClone(); var replace = new ParadoxReplaceExtern(cloned.Variable, new IndexerExpression(cloned.Collection, new LiteralExpression(i))); replace.Run(cloned.Body); result.Add(cloned.Body); } Visit((Node)result); return result; } else { Visit((Node)forEachStatement); parsingInfo.ForEachStatements.Add(new StatementNodeCouple(forEachStatement, ParentNode)); return forEachStatement; } }
/// <summary> /// Creates a ForStatement with the same behavior /// </summary> /// <param name="forEachStatement">the ForEachStatement</param> /// <returns>the ForStatement</returns> private static ForStatement ExpandForEachStatement(ForEachStatement forEachStatement) { if (forEachStatement != null) { var collec = forEachStatement.Collection.TypeInference.Declaration as Variable; LiteralExpression dimLit = null; if (collec.Type is ArrayType) { if ((collec.Type as ArrayType).Dimensions.Count == 1) { dimLit = (collec.Type as ArrayType).Dimensions[0] as LiteralExpression; } } if (dimLit != null) { var initializer = new Variable(ScalarType.Int, forEachStatement.Variable.Name.Text + "Iter", new LiteralExpression(0)); var vre = new VariableReferenceExpression(initializer.Name); var condition = new BinaryExpression(BinaryOperator.Less, vre, dimLit); var next = new UnaryExpression(UnaryOperator.PreIncrement, vre); ForStatement forStatement = new ForStatement(new DeclarationStatement(initializer), condition, next); var body = new BlockStatement(); var variable = forEachStatement.Variable; variable.InitialValue = new IndexerExpression(forEachStatement.Collection, new VariableReferenceExpression(initializer)); body.Statements.Add(new DeclarationStatement(variable)); if (forEachStatement.Body is BlockStatement) body.Statements.AddRange((forEachStatement.Body as BlockStatement).Statements); else body.Statements.Add(forEachStatement.Body); forStatement.Body = body; return forStatement; } // TODO: multidimension-array? // TODO: unroll? // TODO: multiple foreach? } return null; }
protected virtual void Visit(ForEachStatement forEachStatement) { WriteLinkLine(forEachStatement); if (forEachStatement.Variable == null) { localVariableCount++; Identifier parameterType; Identifier parameterMember; if (!TryParameters(forEachStatement.Collection, out parameterType, out parameterMember)) { Write(@"#error ""Unexpected parameter for 'foreach params' ["); VisitDynamic(forEachStatement.Collection); WriteLine(@"]. Expecting single property access"""); return; } string variable = "____" + localVariableCount; Write("foreach(").Write("var ").Write(variable).Write(" in "); VisitDynamic(forEachStatement.Collection); WriteLine(")"); var statement = forEachStatement.Body as BlockStatement; if (statement == null) { statement = new BlockStatement {Span = forEachStatement.Body.Span}; statement.Statements.Add(forEachStatement.Body); } AddPushPopParameters(statement, parameterType, parameterMember, new VariableReferenceExpression(variable), forEachStatement.Span); VisitDynamic(statement); localVariableCount--; } else { Write("foreach("); IsVisitingVariableInlines = true; VisitDynamic(forEachStatement.Variable); IsVisitingVariableInlines = false; Write(" in "); VisitDynamic(forEachStatement.Collection); Write(")"); WriteLine(); VisitDynamic(forEachStatement.Body); } }