Example #1
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;
            }
        }
Example #2
0
        private static AstBlock EncloseDoWhile(GotoStatement stmt, AstBlock block, IAstNode first)
        {
            if (block.Type == AstBlockType.DoWhile && first == block.First)
            {
                // We only need to insert the continue if we're not at the end of the loop,
                // or if our condition is different from the loop condition.
                if (Next(stmt.Goto) != null || block.Condition != stmt.Condition)
                {
                    EncloseSingleInst(stmt, Instruction.LoopContinue);
                }

                // Modify the do-while condition to allow it to continue.
                if (!ContainsCondComb(block.Condition, Instruction.LogicalOr, stmt.Condition))
                {
                    block.OrCondition(stmt.Condition);
                }

                return(block);
            }

            return(Enclose(block, AstBlockType.DoWhile, stmt.Condition, first, stmt.Goto));
        }