private static void Lift(GotoStatement stmt) { AstBlock block = ParentBlock(stmt.Goto); AstBlock[] path = BackwardsPath(block, ParentBlock(stmt.Label)); AstBlock loopFirstStmt = path[path.Length - 1]; if (loopFirstStmt.Type == AstBlockType.Else) { loopFirstStmt = Previous(loopFirstStmt) as AstBlock; if (loopFirstStmt == null || loopFirstStmt.Type != AstBlockType.If) { throw new InvalidOperationException("Found an else without a matching if."); } } AstBlock newBlock = EncloseDoWhile(stmt, block, loopFirstStmt); block.Remove(stmt.Goto); newBlock.AddFirst(stmt.Goto); stmt.IsLoop = false; }
private static void EncloseSingleInst(GotoStatement stmt, Instruction inst) { AstBlock block = ParentBlock(stmt.Goto); AstBlock newBlock = new AstBlock(AstBlockType.If, stmt.Condition); block.AddAfter(stmt.Goto, newBlock); newBlock.AddFirst(new AstOperation(inst)); }
private static void MoveInward(GotoStatement stmt) { AstBlock block = ParentBlock(stmt.Goto); AstBlock[] path = BackwardsPath(block, ParentBlock(stmt.Label)); for (int index = path.Length - 1; index >= 0; index--) { AstBlock child = path[index]; AstBlock last = child; if (child.Type == AstBlockType.If) { // Modify the if condition to allow it to be entered by the goto. if (!ContainsCondComb(child.Condition, Instruction.LogicalOr, stmt.Condition)) { child.OrCondition(stmt.Condition); } } else if (child.Type == AstBlockType.Else) { // Modify the matching if condition to force the else to be entered by the goto. if (!(Previous(child) is AstBlock ifBlock) || ifBlock.Type != AstBlockType.If) { throw new InvalidOperationException("Found an else without a matching if."); } IAstNode cond = InverseCond(stmt.Condition); if (!ContainsCondComb(ifBlock.Condition, Instruction.LogicalAnd, cond)) { ifBlock.AndCondition(cond); } last = ifBlock; } Enclose(block, AstBlockType.If, stmt.Condition, Next(stmt.Goto), last); block.Remove(stmt.Goto); child.AddFirst(stmt.Goto); block = child; } }