protected override SyntaxNode VisitForSyntax(ForSyntax pNode) { //Rewrite for statements with iterator arrays to normal for statements if (pNode.Iterator != null) { var i = SyntaxFactory.Identifier("!i"); i.SetType(SmallTypeCache.Int); var postOp = pNode.Reverse ? UnaryExpressionOperator.PostDecrement : UnaryExpressionOperator.PostIncrement; UnaryExpressionSyntax finalizer = SyntaxFactory.UnaryExpression(i, postOp); SyntaxNode end = null; DeclarationSyntax decl = null; //Save itvar in case we are looping in a case body var rw = _rewrite; var it = _itVar; //Declare our iterator outside the for loop //This will help if our iterator is complex like a function call var iterVar = SyntaxFactory.Identifier("!iter"); iterVar.SetType(pNode.Iterator.Type); var iterDecl = SyntaxFactory.SingleDeclaration(iterVar, pNode.Iterator); if (pNode.Iterator.Type.IsArray) { //We are iterating over an array //Reverse loops will start at Array.Length and decrement to 0 //Normal loops will start at 0 and increment to Array.Length if (pNode.Reverse) { var length = SyntaxFactory.UnaryExpression(iterVar, UnaryExpressionOperator.Length); length.SetType(SmallTypeCache.Int); decl = SyntaxFactory.SingleDeclaration(i, SyntaxFactory.BinaryExpression(length, BinaryExpressionOperator.Subtraction, SyntaxFactory.NumericLiteral(1))); end = SyntaxFactory.NumericLiteral(0); } else { decl = SyntaxFactory.SingleDeclaration(i, SyntaxFactory.NumericLiteral(0)); end = SyntaxFactory.UnaryExpression(iterVar, UnaryExpressionOperator.Length); ((UnaryExpressionSyntax)end).SetType(SmallTypeCache.Int); } _itVar = SyntaxFactory.ArrayAccess(iterVar, i); ((ArrayAccessSyntax)_itVar).SetType(iterVar.Type); } else if (pNode.Iterator.Type.IsAssignableFrom(_enumerable)) { //We are iterating over an enumerable //Reverse loops will start at Count and decrement to 0 //Normal loops will start at 0 and increment to Count if (pNode.Reverse) { var count = SyntaxFactory.MemberAccess(iterVar, SyntaxFactory.Identifier("Count")); decl = SyntaxFactory.SingleDeclaration(i, SyntaxFactory.BinaryExpression(count, BinaryExpressionOperator.Subtraction, SyntaxFactory.NumericLiteral(1))); end = SyntaxFactory.NumericLiteral(0); } else { decl = SyntaxFactory.SingleDeclaration(i, SyntaxFactory.NumericLiteral(0)); end = SyntaxFactory.MemberAccess(iterVar, SyntaxFactory.Identifier("Count")); } _itVar = SyntaxFactory.MemberAccess(iterVar, SyntaxFactory.MethodCall("ItemAt", new List <SyntaxNode>() { SyntaxFactory.Identifier("!i") })); } else { //Some bad type. We can't rewrite if it isn't array or enumerable return(base.VisitForSyntax(pNode)); } var op = pNode.Reverse ? BinaryExpressionOperator.GreaterThanOrEqual : BinaryExpressionOperator.LessThan; var condition = SyntaxFactory.BinaryExpression(i, op, end); condition.SetType(SmallTypeCache.Boolean); var body = (BlockSyntax)Visit(pNode.Body); var forStatement = SyntaxFactory.For(new List <DeclarationSyntax>() { decl }, condition, new List <SyntaxNode>() { finalizer }, body); //Restore our it for any other nested loops _itVar = it; _rewrite = rw; //Return our iterator declaration and for rewrite return(SyntaxFactory.Block(new List <SyntaxNode>() { iterDecl, forStatement })); } return(base.VisitForSyntax(pNode)); }
protected virtual SyntaxNode VisitArrayAccessSyntax(ArrayAccessSyntax pNode) { return(SyntaxFactory.ArrayAccess(pNode.Identifier, Visit(pNode.Index))); }