Ejemplo n.º 1
0
        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;
        }
Ejemplo n.º 2
0
        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));
        }
Ejemplo n.º 3
0
        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;
            }
        }