public ForStatement TransformFor(ExpressionStatement node)
        {
            Match m1 = variableAssignPattern.Match(node);

            if (!m1.Success)
            {
                return(null);
            }
            var     variable = m1.Get <IdentifierExpression>("variable").Single().GetILVariable();
            AstNode next     = node.NextSibling;

            if (next is ForStatement forStatement && ForStatementUsesVariable(forStatement, variable))
            {
                node.Remove();
                next.InsertChildAfter(null, node, ForStatement.InitializerRole);
                return((ForStatement)next);
            }
            Match m3 = forPattern.Match(next);

            if (!m3.Success)
            {
                return(null);
            }
            // ensure the variable in the for pattern is the same as in the declaration
            if (variable != m3.Get <IdentifierExpression>("ident").Single().GetILVariable())
            {
                return(null);
            }
            WhileStatement loop = (WhileStatement)next;

            // Cannot convert to for loop, because that would change the semantics of the program.
            // continue in while jumps to the condition block.
            // Whereas continue in for jumps to the increment block.
            if (loop.DescendantNodes(DescendIntoStatement).OfType <Statement>().Any(s => s is ContinueStatement))
            {
                return(null);
            }
            node.Remove();
            BlockStatement newBody = new BlockStatement();

            foreach (Statement stmt in m3.Get <Statement>("statement"))
            {
                newBody.Add(stmt.Detach());
            }
            forStatement = new ForStatement();
            forStatement.CopyAnnotationsFrom(loop);
            forStatement.Initializers.Add(node);
            forStatement.Condition = loop.Condition.Detach();
            forStatement.Iterators.Add(m3.Get <Statement>("increment").Single().Detach());
            forStatement.EmbeddedStatement = newBody;
            loop.ReplaceWith(forStatement);
            return(forStatement);
        }
        public ForStatement TransformFor(ExpressionStatement node)
        {
            Match m1 = variableAssignPattern.Match(node);

            if (!m1.Success)
            {
                return(null);
            }
            var     variableName = m1.Get <IdentifierExpression>("variable").Single().Identifier;
            AstNode next         = node.NextSibling;

            if (next is ForStatement forStatement)
            {
                if ((forStatement.Iterators.FirstOrDefault() is ExpressionStatement stmt &&
                     stmt.Expression is AssignmentExpression assign &&
                     variableName == assign.Left.ToString()) ||
                    (forStatement.Condition is BinaryOperatorExpression cond &&
                     variableName == cond.Left.ToString()))
                {
                    node.Remove();
                    forStatement.InsertChildAfter(null, node, ForStatement.InitializerRole);
                    return(forStatement);
                }
            }
            Match m3 = forPattern.Match(next);

            if (!m3.Success)
            {
                return(null);
            }
            // ensure the variable in the for pattern is the same as in the declaration
            if (variableName != m3.Get <IdentifierExpression>("ident").Single().Identifier)
            {
                return(null);
            }
            WhileStatement loop = (WhileStatement)next;

            node.Remove();
            BlockStatement newBody = new BlockStatement();

            foreach (Statement stmt in m3.Get <Statement>("statement"))
            {
                newBody.Add(stmt.Detach());
            }
            forStatement = new ForStatement();
            forStatement.CopyAnnotationsFrom(loop);
            forStatement.Initializers.Add(node);
            forStatement.Condition = loop.Condition.Detach();
            forStatement.Iterators.Add(m3.Get <Statement>("increment").Single().Detach());
            forStatement.EmbeddedStatement = newBody;
            loop.ReplaceWith(forStatement);
            return(forStatement);
        }
        public ForStatement TransformFor(ExpressionStatement node)
        {
            Match m1 = variableAssignPattern.Match(node);

            if (!m1.Success)
            {
                return(null);
            }
            var     variable = m1.Get <IdentifierExpression>("variable").Single().GetILVariable();
            AstNode next     = node.NextSibling;

            if (next is ForStatement forStatement && ForStatementUsesVariable(forStatement, variable))
            {
                node.Remove();
                next.InsertChildAfter(null, node, ForStatement.InitializerRole);
                return((ForStatement)next);
            }
            Match m3 = forPattern.Match(next);

            if (!m3.Success)
            {
                return(null);
            }
            // ensure the variable in the for pattern is the same as in the declaration
            if (variable != m3.Get <IdentifierExpression>("ident").Single().GetILVariable())
            {
                return(null);
            }
            WhileStatement loop = (WhileStatement)next;

            node.Remove();
            BlockStatement newBody = new BlockStatement();

            foreach (Statement stmt in m3.Get <Statement>("statement"))
            {
                newBody.Add(stmt.Detach());
            }
            forStatement = new ForStatement();
            forStatement.CopyAnnotationsFrom(loop);
            forStatement.Initializers.Add(node);
            forStatement.Condition = loop.Condition.Detach();
            forStatement.Iterators.Add(m3.Get <Statement>("increment").Single().Detach());
            forStatement.EmbeddedStatement = newBody;
            loop.ReplaceWith(forStatement);
            return(forStatement);
        }
        public DoWhileStatement TransformDoWhile(WhileStatement whileLoop)
        {
            Match m = doWhilePattern.Match(whileLoop);

            if (m.Success)
            {
                DoWhileStatement doLoop = new DoWhileStatement();
                doLoop.Condition = new UnaryOperatorExpression(UnaryOperatorType.Not, m.Get <Expression>("condition").Single().Detach());
                //doLoop.Condition.AcceptVisitor(new PushNegation(), null);
                BlockStatement block = (BlockStatement)whileLoop.EmbeddedStatement;
                block.Statements.Last().Remove();                 // remove if statement
                doLoop.EmbeddedStatement = block.Detach();
                doLoop.CopyAnnotationsFrom(whileLoop);
                whileLoop.ReplaceWith(doLoop);

                // we may have to extract variable definitions out of the loop if they were used in the condition:
                foreach (var varDecl in block.Statements.OfType <VariableDeclarationStatement>())
                {
                    VariableInitializer v = varDecl.Variables.Single();
                    if (doLoop.Condition.DescendantsAndSelf.OfType <IdentifierExpression>().Any(i => i.Identifier == v.Name))
                    {
                        AssignmentExpression assign = new AssignmentExpression(new IdentifierExpression(v.Name), v.Initializer.Detach());
                        // move annotations from v to assign:
                        assign.CopyAnnotationsFrom(v);
                        v.RemoveAnnotations <object>();
                        // remove varDecl with assignment; and move annotations from varDecl to the ExpressionStatement:
                        varDecl.ReplaceWith(new ExpressionStatement(assign).CopyAnnotationsFrom(varDecl));
                        varDecl.RemoveAnnotations <object>();

                        // insert the varDecl above the do-while loop:
                        doLoop.Parent.InsertChildBefore(doLoop, varDecl, BlockStatement.StatementRole);
                    }
                }
                return(doLoop);
            }
            return(null);
        }