/* * LoopBlock (c) 1998 Jochen Hoenicke * * You may distribute under the terms of the GNU General Public License. * * IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" * BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE, * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * $Id$ */ package jode.flow; import jode.*; /** * This is the structured block for an Loop block. */ public class LoopBlock extends BreakableBlock { public static final int WHILE = 0; public static final int DOWHILE = 1; public static final int FOR = 2; public static final Instruction TRUE = new Expression(new ConstOperator(MyType.tBoolean, "1"), new Expression[0]); public static final Instruction FALSE = new Expression(new ConstOperator(MyType.tBoolean, "0"), new Expression[0]); /** * The condition. Must be of boolean type. */ Instruction cond; /** * The init instruction, only valid if type == FOR. */ Instruction init; /** * The increase instruction, only valid if type == FOR. */ Instruction incr; /** * The type of the loop. This must be one of DOWHILE, WHILE or FOR. */ int type; /** * The body of this loop. This is always a valid block and not null */ StructuredBlock bodyBlock; /** * Returns the block where the control will normally flow to, when * the given sub block is finished (not ignoring the jump * after this block). (This is overwritten by SequentialBlock and * SwitchBlock). If this isn't called with a direct sub block, * the behaviour is undefined, so take care. * @return null, if the control flows to another FlowBlock. */ public StructuredBlock getNextBlock(StructuredBlock subBlock) { return this; } public FlowBlock getNextFlowBlock(StructuredBlock subBlock) { return null; } public LoopBlock(int type, Instruction cond) { this.type = type; this.cond = cond; this.mayChangeJump = (cond == TRUE); } public void setBody(StructuredBlock body) { bodyBlock = body; bodyBlock.outer = this; body.setFlowBlock(flowBlock); } public Instruction getCondition() { return cond; } public void setCondition(Instruction cond) { this.cond = cond; mayChangeJump = false; } public int getType() { return type; } public void setType(int type) { this.type = type; } /** * Replaces the given sub block with a new block. * @param oldBlock the old sub block. * @param newBlock the new sub block. * @return false, if oldBlock wasn't a direct sub block. */ public boolean replaceSubBlock(StructuredBlock oldBlock, StructuredBlock newBlock) { if (bodyBlock == oldBlock) bodyBlock = newBlock; else return false; return true; } /** * Returns all sub block of this structured block. */ public StructuredBlock[] getSubBlocks() { StructuredBlock[] result = { bodyBlock }; return result; } public void dumpInstruction(TabbedPrintWriter writer) throws java.io.IOException { boolean needBrace = ! (bodyBlock instanceof InstructionBlock); switch (type) { case WHILE: writer.print("while ("+cond.toString()+")"); break; case DOWHILE: writer.print("do"); break; case FOR: writer.print("for ("+(init != null ? init.toString() : "") + "; "+cond.toString()+"; "+incr.toString()+")"); break; } writer.println( needBrace?" {": ""); writer.tab(); bodyBlock.dumpSource(writer); writer.untab(); if (type == DOWHILE) writer.println((needBrace?"} ": "")+ "while ("+cond.toString()+")"); else if (needBrace) writer.println("}"); } }