git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@13 379699f6-c40d-0410-875b-85095c16579estable
parent
5c4d86e1cb
commit
83e1e75c5d
@ -0,0 +1,50 @@ |
||||
/* |
||||
* EmptyBlock (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; |
||||
|
||||
/** |
||||
* This is the structured block for an empty block. |
||||
*/ |
||||
public class EmptyBlock extends StructuredBlock { |
||||
Instruction instr; |
||||
|
||||
SimpleInstruction(Instruction instr) { |
||||
in = new Vector(); |
||||
out = new Vector(); |
||||
this.instr = instr; |
||||
if (instr instanceof LocalVarOperator) { |
||||
LocalVarOperator varOp = (LocalVarOperator) instr; |
||||
if (varOp.isRead()) |
||||
in.addElement(varOp.getLocalInfo()); |
||||
else /* if (varOp.isWrite()) */ |
||||
out.addElement(varOp.getLocalInfo()); |
||||
} |
||||
} |
||||
|
||||
public void dumpSource(TabbedPrintWriter writer) |
||||
throws java.io.IOException |
||||
{ |
||||
if (!(instr instanceof NopOperator)) { |
||||
if (instr.getType() != MyType.tVoid) |
||||
writer.print("push "); |
||||
writer.println(instr.toString()+";"); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,32 @@ |
||||
/* jode.flow.FinallyBlock (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; |
||||
|
||||
/** |
||||
* A FinallyBlock represents the instructions and try catch regions |
||||
* that are generated by javac when you write a finally block. |
||||
* |
||||
* We detect such a block when we look at the exception table. There |
||||
* is always an "any"-exception region (exception class is null) that |
||||
* surrounds the first block. The synchronized-blocks create the same |
||||
* region, so we have to take care of this. |
||||
*/ |
||||
|
||||
public FinallyBlock extends StructuredBlock { |
||||
} |
@ -0,0 +1,252 @@ |
||||
/* |
||||
* FlowBlock (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; |
||||
|
||||
/** |
||||
* A flow block is the structure of which the flow graph consists. A |
||||
* flow block contains structured code together with some conditional |
||||
* or unconditional jumps to the head of other flow blocks. |
||||
* |
||||
* We do a T1/T2 analysis to combine all flow blocks to a single. If |
||||
* the graph isn't reducible that doesn't work, but java can only |
||||
* produce reducible flow graphs. |
||||
*/ |
||||
public class FlowBlock { |
||||
|
||||
/** |
||||
* The starting address of this flow block. This is mainly used |
||||
* to produce the source code in code order. |
||||
*/ |
||||
int addr; |
||||
|
||||
/** |
||||
* The outermost structructed block in this flow block. |
||||
*/ |
||||
StructuredBlock block; |
||||
|
||||
/** |
||||
* The last modified structured block. |
||||
*/ |
||||
StructuredBlock lastModified; |
||||
|
||||
/** |
||||
* All jumps that this flow block contains. |
||||
*/ |
||||
Vector successors; |
||||
|
||||
/** |
||||
* This is a vector of flow blocks, which reference this block. |
||||
* Only if this vector contains exactly one element, it can be |
||||
* moved into the preceding flow block. |
||||
*/ |
||||
Vector predecessors; |
||||
|
||||
public void optimizeJumps(FlowBlock successor) { |
||||
/* remove all unconditional jumps to the successor which have the |
||||
* end of the block as normal successor. |
||||
*/ |
||||
|
||||
/* replace all conditional jumps to the successor, which are followed |
||||
* by a block which has the end of the block as normal successor, |
||||
* with "if (not condition) block". |
||||
*/ |
||||
|
||||
/* if there are jumps in a while block, which has the end of |
||||
* the block as normal successor or is followed by a |
||||
* unconditional jump to successor, replace jumps with breaks |
||||
* to the while block. If the condition of the while is true, |
||||
* and the first instruction is converted to a conditional break |
||||
* remove that break and use the condition in the while block. |
||||
*/ |
||||
|
||||
|
||||
/* if there are jumps in an switch block, which has as normal |
||||
* successor the end of this FlowBlock, replace them with a |
||||
* break to the switch block. |
||||
* if there successor isn't the end of this FlowBlock, but |
||||
* there are many, or the next rule could work (some more |
||||
* heuristics?) and there is currently no flow to the end of |
||||
* the switch block, replace all such successors with a break |
||||
* and add a new unconditional jump after the switch block. */ |
||||
|
||||
/* if there are unconditional jumps in an if-then block, which |
||||
* have as normal successor the end of the if-then block, and |
||||
* the if-then block is followed by a single block, which has |
||||
* as normal successor the end of the block, then replace |
||||
* the if-then block with a if-then-else block and remove the |
||||
* unconditional jumps. |
||||
*/ |
||||
} |
||||
|
||||
|
||||
/* Special cases: |
||||
* |
||||
* try-header |
||||
* |- first instruction |
||||
* | ... |
||||
* | last instruction |
||||
* |- optional jump (last+1) |
||||
* | ... |
||||
* `- catch block |
||||
* |
||||
* A try block may have many try-headers with different catch blocks |
||||
* and there may be a finally block: |
||||
* |
||||
* try-header any |
||||
* | try-header |
||||
* |--|- first instruction |
||||
* | | ... |
||||
* | | every jump to outside is preceded by jsr finally |
||||
* | | ... |
||||
* | | last instruction |
||||
* | |- optional jump after catch block (last+1) |
||||
* | | ... | |
||||
* | `- catch block | |
||||
* | ... | |
||||
* | ,-----------------' |
||||
* | |-jump after all catch blocks |
||||
* | v |
||||
* | jsr finally -----------------, |
||||
* |- jump after finally | |
||||
* `- catch any (local_n) v |
||||
* jsr finally ---------------->| |
||||
* throw local_n; | |
||||
* finally: <-----------------------' |
||||
* astore_n |
||||
* ... |
||||
* return_n |
||||
* |
||||
* |
||||
* flow-block |
||||
* finally-block |
||||
* ---> try-header |
||||
* finally { |
||||
* ---> first-finally-instruction |
||||
* |
||||
* A synchronized block uses a similar technique: |
||||
* |
||||
* local_x = monitor object; |
||||
* monitorenter local_x |
||||
* try-header any |
||||
* |- syncronized block |
||||
* | ... |
||||
* | every jump to outside is preceded by jsr monexit ---, |
||||
* | ... | |
||||
* |- monitorexit local_x | |
||||
* | jump after this block (without jsr monexit) | |
||||
* `- catch any (local_n) | |
||||
* monitorexit local_x | |
||||
* throw local_n | |
||||
* monexit: <-----------------------------------------------' |
||||
* astore_n |
||||
* monitorexit local_x |
||||
* return_n |
||||
*/ |
||||
|
||||
public boolean doT1 { |
||||
/* search successor with smallest addr. */ |
||||
|
||||
/* check if this successor has only this block as predecessor. */ |
||||
/* if not, return false. */ |
||||
|
||||
/* The switch case: if the last instruction in this block is a |
||||
* switch block, and all jumps to successor lie in a single case, |
||||
* or if all jumps |
||||
* which doesn't have the end of the block as normal |
||||
* successor, combine the successor with that block. But this |
||||
* doesn't catch all cases. |
||||
*/ |
||||
|
||||
optimizeJumps(successor); |
||||
|
||||
/* if the successor is the dummy return instruction, replace all |
||||
* jumps with a return. |
||||
*/ |
||||
|
||||
/* If there are further jumps, put a do/while(0) block around |
||||
* current block and replace every necessary jump with a break |
||||
* to the do/while block. Then combine the block with a |
||||
* sequential composition. */ |
||||
} |
||||
|
||||
public boolean doT2() { |
||||
/* If there are no jumps to the beginning of this flow block |
||||
* or if this block has other predecessors which weren't |
||||
* considered yet, return false. |
||||
*/ |
||||
|
||||
/* If there is only one jump to the beginning and it is the |
||||
* last jump and (there is a do/while(0) block surrounding |
||||
* everything but the last instruction, or the last |
||||
* instruction is a increase/decrease statement), replace the |
||||
* do/while(0) with a for(;;last_instr) resp. create a new one |
||||
* and replace breaks to do/while with continue. |
||||
*/ |
||||
{ |
||||
/* Otherwise: */ |
||||
optimizeJumps(this); |
||||
|
||||
/* create a new while(true) block. |
||||
*/ |
||||
} |
||||
|
||||
/* if there are further jumps to this, replace every jump with a |
||||
* continue to while block and return true. |
||||
*/ |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* A structured block describes a structured program. There may be a |
||||
* Jump after a block (even after a inner structured block), but the |
||||
* goal is, to remove all such jumps and make a single flow block.<p> |
||||
* |
||||
* There are following types of structured blocks: <ul> |
||||
* <li>if-then-(else)-block (IfThenElseBlock)</li> |
||||
* <li>(do)-while/for-block (LoopBlock) |
||||
* <li>switch-block (SwitchBlock) |
||||
* <li>try-catch-finally-block (TryBlock) |
||||
* <li>A block consisting of sub blocks (SequentialBlock) |
||||
* </ul> |
||||
*/ |
||||
public class StructuredBlock { |
||||
/** The surrounding block, or null if this is the outermost block in a |
||||
* flow block. |
||||
*/ |
||||
StructuredBlock parent; |
||||
|
||||
/** The flow block to which this structured block belongs. |
||||
*/ |
||||
FlowBlock flow; |
||||
|
||||
} |
||||
|
||||
public class ConditionalJump extends Jump { |
||||
Expression condition; |
||||
StructuredBlock prev; |
||||
FlowBlock parent; |
||||
FlowBlock jump, nojump; |
||||
} |
||||
|
||||
public class UnconditionalJump extends Jump { |
||||
StructuredBlock prev; |
||||
FlowBlock parent; |
||||
FlowBlock jump; |
||||
} |
@ -0,0 +1,46 @@ |
||||
/* InstructionBlock (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; |
||||
|
||||
/** |
||||
* This is the structured block for atomic instructions. |
||||
*/ |
||||
public class InstructionBlock extends StructuredBlock { |
||||
Instruction instr; |
||||
|
||||
InstructionBlock(Instruction instr) { |
||||
in = new Vector(); |
||||
out = new Vector(); |
||||
this.instr = instr; |
||||
if (instr instanceof LocalVarOperator) { |
||||
LocalVarOperator varOp = (LocalVarOperator) instr; |
||||
if (varOp.isRead()) |
||||
in.addElement(varOp.getLocalInfo()); |
||||
else /* if (varOp.isWrite()) */ |
||||
out.addElement(varOp.getLocalInfo()); |
||||
} |
||||
} |
||||
|
||||
public void dumpSource(TabbedPrintWriter writer) |
||||
throws java.io.IOException |
||||
{ |
||||
writer.println("/* empty */"); |
||||
} |
||||
} |
@ -0,0 +1,59 @@ |
||||
/* jode.flow.RawTryCatchBlock (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; |
||||
|
||||
/** |
||||
* A RawTryCatchBlock is created for each exception in the |
||||
* ExceptionHandlers-Attribute. <p> |
||||
* |
||||
* For each catch block (there may be more than one catch block |
||||
* appending a single try block) and for each finally and each |
||||
* synchronized block such a RawTryCatchBlock is created. The |
||||
* finally/synchronized-blocks have a null exception type so that they |
||||
* are easily distinguishable from the catch blocks. <p> |
||||
* |
||||
* A RawTryCatchBlock is an intermediate representation that gets |
||||
* converted later to a CatchBlock, a FinallyBlock or a |
||||
* SynchronizedBlock (after the body is parsed). |
||||
* |
||||
* @date 1998/09/16 |
||||
* @author Jochen Hoenicke |
||||
* @see CatchBlock |
||||
* @see FinallyBlock |
||||
* @see SynchronizedBlock |
||||
*/ |
||||
|
||||
public RawTryCatchBlock extends StructuredBlock { |
||||
|
||||
/** |
||||
* An unconditional jump to the EndBlock. |
||||
*/ |
||||
Jump EndBlock; |
||||
|
||||
/** |
||||
* An unconditional jump to the CatchBlock. |
||||
*/ |
||||
Jump CatchBlock; |
||||
|
||||
/** |
||||
* The type of the exception that is catched. This is null for a |
||||
* synchronized/finally block |
||||
*/ |
||||
Type type; |
||||
} |
@ -0,0 +1,174 @@ |
||||
/* |
||||
* StructuredBlock (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; |
||||
|
||||
/** |
||||
* A structured block is the building block of the source programm. |
||||
* For every program construct like if, while, try, or blocks there is |
||||
* a corresponding structured block. |
||||
* |
||||
* Some of these Block are only intermediate representation, that get |
||||
* converted to another block later. |
||||
* |
||||
* Every block has to handle the local variables that it contains. |
||||
* This is done by the in/out vectors and the local variable structure |
||||
* themself. Every local variable used in this structured block is |
||||
* either in or out. |
||||
* |
||||
* There are following types of structured blocks: |
||||
* <ul> |
||||
* <li>if-then-(else)-block (IfThenElseBlock) |
||||
* <li>(do)-while/for-block (LoopBlock) |
||||
* <li>switch-block (SwitchBlock) |
||||
* <li>try-catch-block (CatchBlock) |
||||
* <li>try-finally-block (FinallyBlock) |
||||
* <li>synchronized-block (SynchronizedBlock) |
||||
* <li>one-instruction (InstructionBlock) |
||||
* <li>empty-block (EmptyBlock) |
||||
* <li>multi-blocks-block (SequentialBlock) |
||||
* </ul> |
||||
*/ |
||||
|
||||
public abstract class StructuredBlock { |
||||
/* Invariants: |
||||
* in.intersection(out) = empty |
||||
* outer != null => flowblock = outer.flowblock |
||||
* outer == null => flowblock.block = this |
||||
* jump == null => outer != null |
||||
* either getNextBlock() != null |
||||
* or getNextFlowBlock() != null or outer == null |
||||
* either outer.getNextBlock(this) != null |
||||
* or outer.getNextFlowBlock(this) != null |
||||
*/ |
||||
|
||||
/** |
||||
* The in locals. This are the locals, which are used in this |
||||
* block and whose values may be the result of a assignment |
||||
* outside of the whole flow block. That means, that there is a |
||||
* path from the start of the current flow block, on which the |
||||
* local variable is never assigned |
||||
*/ |
||||
Vector in; |
||||
|
||||
/** |
||||
* The out locals. This are the locals, which must be overwritten |
||||
* until the end of this block. That means, that all paths form |
||||
* the start of the current flow block to the end of this |
||||
* structured block contain a (unconditional) assignment to this |
||||
* local |
||||
*/ |
||||
Vector out; |
||||
|
||||
/** |
||||
* The surrounding structured block. If this is the outermost |
||||
* block in a flow block, outer is null. |
||||
*/ |
||||
StructuredBlock outer; |
||||
|
||||
/** |
||||
* The flow block in which this structured block lies. |
||||
*/ |
||||
FlowBlock flowblock; |
||||
|
||||
/** |
||||
* The jump that follows on this block, or null if there is no |
||||
* jump, but the control flows normal (only allowed if |
||||
* getNextBlock != null). |
||||
*/ |
||||
Jump jump; |
||||
|
||||
/** |
||||
* Returns the block where the control will normally flow to, when |
||||
* this block is finished (ignoring the jump after this block). |
||||
*/ |
||||
StructuredBlock getNextBlock() { |
||||
if (outer != null) |
||||
outer.getNextBlock(this); |
||||
else |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns the flow block where the control will normally flow to, |
||||
* when this block is finished (ignoring the jump after this |
||||
* block). |
||||
* @return null, if the control flows into a non empty structured |
||||
* block or if this is the outermost block. |
||||
*/ |
||||
FlowBlock getNextFlowBlock() { |
||||
if (outer != null) |
||||
outer.getNextFlowBlock(this); |
||||
else |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Checks if the jump to the outside has correct monitorexit and |
||||
* jsr instructions attached. |
||||
* @return null, if everything is okay, and a diagnostic message that |
||||
* should be put in a comment otherwise. |
||||
*/ |
||||
String checkJump(Jump jump) { |
||||
if (outer != null) |
||||
return outer.checkJump(jump); |
||||
else if (jump.hasAttachments()) |
||||
return "Unknown attachments: "+jump.describeAttachments() |
||||
else |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Returns the block where the control will normally flow to, when |
||||
* the given sub block is finished (<em>not</em> 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. */ |
||||
StructuredBlock getNextBlock(StructuredBlock subBlock) { |
||||
if (jump != null) |
||||
return null; |
||||
return getNextBlock(); |
||||
} |
||||
|
||||
FlowBlock getNextFlowBlock(StructuredBlock subBlock) { |
||||
if (jump != null) |
||||
return jump; |
||||
return getNextFlowBlock(); |
||||
} |
||||
|
||||
/** |
||||
* 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. |
||||
*/ |
||||
boolean replaceSubBlock(StructuredBlock oldBlock, |
||||
StructuredBlock newBlock) { |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* Print the source code for this structured block. This may be |
||||
* called only once, because it remembers which local variables |
||||
* were declared. |
||||
*/ |
||||
public abstract void dumpSource(TabbedPrintWriter writer) |
||||
throws java.io.IOException; |
||||
} |
Loading…
Reference in new issue