public void AcceptLoopBlock(LoopBlock stmt) { IfStatement cond = stmt.Body.AsSingleStatement() as IfStatement; if (cond == null) { return; } if (cond.Conditions.Count != 1 || cond.Branches.Count != 2) { return; } IList <Statement> trueBranch = cond.Branches[0].AsStatementList(); if (trueBranch.Count == 0 || !trueBranch.Last().Equals(new ContinueLoopStatement() { Loop = stmt })) { return; } IList <Statement> falseBranch = cond.Branches[1].AsStatementList(); if (falseBranch.Count == 0) { return; } #if false BreakLoopStatement breaker = new BreakLoopStatement() { Loop = stmt }; Statement trailer = cond.Branches[1].Clone; trailer.RemoveAll(breaker); #endif Statement trailer = cond.Branches[1].Clone; BreakLoopReplacer blr = new BreakLoopReplacer(stmt); trailer.Accept(blr); if (trailer.NeedsLoopScope(stmt)) { return; } #if false CompoundStatement trailer = new CompoundStatement(); trailer.Statements.AddRange(falseBranch.Take(falseBranch.Count - 1)); if (trailer.NeedsLoopScope(stmt)) { return; } BreakLoopStatement breaker = falseBranch.Last() as BreakLoopStatement; if (breaker == null) { return; } if (breaker.Loop.IsAncestor(stmt)) { /* Consider the following situation: * * L1: loop * some outer loop work * L2: loop * if someCondition then * do something * continue L2 * else * do something different * break L1 * end if * end loop L2 * end loop L1 * * As the inner break statement breaks the outer loop, this loop * must be transformed into the following code: * * L1: loop * some outer loop work * while someCondition loop * do something * end while * do something different * break L1 * end loop * */ if (breaker.Loop != stmt) { trailer.Statements.Add(breaker); } } else { return; } #endif CompoundStatement newBody = new CompoundStatement(); newBody.Statements.AddRange(trueBranch.Take(trueBranch.Count - 1)); LoopBlock whileBlock = (LoopBlock)stmt.Clone; whileBlock.HeadCondition = cond.Conditions[0]; whileBlock.Body = newBody; whileBlock.Trailer = trailer; Result = whileBlock; }
public void AcceptLoopBlock(LoopBlock stmt) { IfStatement cond = stmt.Body.AsSingleStatement() as IfStatement; if (cond == null) return; if (cond.Conditions.Count != 1 || cond.Branches.Count != 2) return; IList<Statement> trueBranch = cond.Branches[0].AsStatementList(); if (trueBranch.Count == 0 || !trueBranch.Last().Equals(new ContinueLoopStatement() { Loop = stmt })) return; IList<Statement> falseBranch = cond.Branches[1].AsStatementList(); if (falseBranch.Count == 0) return; #if false BreakLoopStatement breaker = new BreakLoopStatement() { Loop = stmt }; Statement trailer = cond.Branches[1].Clone; trailer.RemoveAll(breaker); #endif Statement trailer = cond.Branches[1].Clone; BreakLoopReplacer blr = new BreakLoopReplacer(stmt); trailer.Accept(blr); if (trailer.NeedsLoopScope(stmt)) return; #if false CompoundStatement trailer = new CompoundStatement(); trailer.Statements.AddRange(falseBranch.Take(falseBranch.Count - 1)); if (trailer.NeedsLoopScope(stmt)) return; BreakLoopStatement breaker = falseBranch.Last() as BreakLoopStatement; if (breaker == null) return; if (breaker.Loop.IsAncestor(stmt)) { /* Consider the following situation: * * L1: loop * some outer loop work * L2: loop * if someCondition then * do something * continue L2 * else * do something different * break L1 * end if * end loop L2 * end loop L1 * * As the inner break statement breaks the outer loop, this loop * must be transformed into the following code: * * L1: loop * some outer loop work * while someCondition loop * do something * end while * do something different * break L1 * end loop * */ if (breaker.Loop != stmt) { trailer.Statements.Add(breaker); } } else return; #endif CompoundStatement newBody = new CompoundStatement(); newBody.Statements.AddRange(trueBranch.Take(trueBranch.Count - 1)); LoopBlock whileBlock = (LoopBlock)stmt.Clone; whileBlock.HeadCondition = cond.Conditions[0]; whileBlock.Body = newBody; whileBlock.Trailer = trailer; Result = whileBlock; }