|
@@ -6,8 +6,6 @@ import javax.swing.tree.DefaultMutableTreeNode;
|
|
|
import javax.swing.tree.MutableTreeNode;
|
|
|
import javax.swing.tree.TreePath;
|
|
|
|
|
|
-import animation.Memory.MemoryType;
|
|
|
-
|
|
|
/**
|
|
|
* represents a line of pseudocode
|
|
|
* @author kolja
|
|
@@ -21,13 +19,6 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
|
|
|
STOP,
|
|
|
CONTINUE
|
|
|
}
|
|
|
-
|
|
|
- public static enum CodeStatus
|
|
|
- {
|
|
|
- UNFINISHED,
|
|
|
- BREAKPOINT,
|
|
|
- FINISHED
|
|
|
- }
|
|
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
|
@@ -39,10 +30,6 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
|
|
|
private CodeLine code;
|
|
|
private boolean selected;
|
|
|
private boolean breakPoint;
|
|
|
- private boolean function;
|
|
|
-
|
|
|
- private StackFrame childFrame; // the stackframe added from this node
|
|
|
- private int currentCodeLine; // next forward code line
|
|
|
|
|
|
public PseudoCodeNode( String description, JTree tree, CodeLine line, AnimatedAlgorithm alg )
|
|
|
{
|
|
@@ -55,10 +42,12 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
|
|
|
selected = false;
|
|
|
this.tree = tree;
|
|
|
breakPoint = false;
|
|
|
- currentCodeLine = -1;
|
|
|
code = line;
|
|
|
- function = false;
|
|
|
- childFrame = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getId()
|
|
|
+ {
|
|
|
+ return nodeId;
|
|
|
}
|
|
|
|
|
|
public void setController( AnimationController c )
|
|
@@ -73,32 +62,6 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
|
|
|
controller = c;
|
|
|
}
|
|
|
|
|
|
- public void writeToStack( Memory m )
|
|
|
- {
|
|
|
- m.declare( "_pos" + nodeId, currentCodeLine, MemoryType.LOCAL );
|
|
|
- m.declare( "_func" + nodeId, function, MemoryType.LOCAL );
|
|
|
- m.declare( "_stack" + nodeId, childFrame, MemoryType.LOCAL );
|
|
|
- currentCodeLine = -1;
|
|
|
- function = false;
|
|
|
- childFrame = null;
|
|
|
- setSelected( false );
|
|
|
- if( children == null )
|
|
|
- return;
|
|
|
- for( Object c : children )
|
|
|
- ((PseudoCodeNode)c).writeToStack( m );
|
|
|
- }
|
|
|
-
|
|
|
- public void loadFromStack( Memory m )
|
|
|
- {
|
|
|
- currentCodeLine = m.read( "_pos" + nodeId, MemoryType.LOCAL );
|
|
|
- function = m.read( "_func" + nodeId, MemoryType.LOCAL );
|
|
|
- childFrame = m.read( "_stack" + nodeId, MemoryType.LOCAL );
|
|
|
- if( children == null )
|
|
|
- return;
|
|
|
- for( Object c : children )
|
|
|
- ((PseudoCodeNode)c).loadFromStack( m );
|
|
|
- }
|
|
|
-
|
|
|
@Override
|
|
|
public void add( MutableTreeNode node )
|
|
|
{
|
|
@@ -208,350 +171,13 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
|
|
|
return breakPoint;
|
|
|
}
|
|
|
|
|
|
- private PseudoCodeNode getForwardNode()
|
|
|
- {
|
|
|
- if( currentCodeLine == -1 )
|
|
|
- return this;
|
|
|
- if( children != null && children.size() > currentCodeLine )
|
|
|
- return ((PseudoCodeNode)children.get( currentCodeLine )).getForwardNode();
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- private PseudoCodeNode getBackwardNode()
|
|
|
- {
|
|
|
- if( currentCodeLine - 1 <= -1 )
|
|
|
- return this;
|
|
|
- if( children != null && children.size() >= currentCodeLine - 1 )
|
|
|
- return ((PseudoCodeNode)children.get( currentCodeLine - 1 )).getBackwardNode();
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- private CodeStatus stepInto( Memory m )
|
|
|
- {
|
|
|
- currentCodeLine = 0;
|
|
|
- if( children == null || children.size() == 0 )
|
|
|
- {
|
|
|
- setSelected( false );
|
|
|
- return CodeStatus.FINISHED;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- setSelected( false );
|
|
|
- return selectChild( 0, m );
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Perform one atomic step of the algorithm. Stops at the end of the program.
|
|
|
- * @return whether the whole stage is finished (afterwards).
|
|
|
- * For example if all steps are finished, then {@code FINISHED} is returned.
|
|
|
- */
|
|
|
- public CodeStatus forwardStep( Memory m )
|
|
|
- {
|
|
|
- m.setCurrent( childFrame );
|
|
|
- if( currentCodeLine == -1 )
|
|
|
- {
|
|
|
- if( !m.isDefined( "node_" + nodeId + "_call", MemoryType.LOCAL ) )
|
|
|
- {
|
|
|
- StackFrame tmp = null;
|
|
|
- if( function )
|
|
|
- {
|
|
|
- tmp = m.removeFrame();
|
|
|
- m.addFrame( tmp ); // a little abuse of the stack to get direct access of the current frame before it could be destroyed by the user defined function
|
|
|
- }
|
|
|
- ControlFlow cf = code.runForward( m );
|
|
|
- switch( cf.getStatus() )
|
|
|
- {
|
|
|
- case ControlFlow.STEP_INTO:
|
|
|
- childFrame = m.removeFrame();
|
|
|
- m.addFrame( childFrame );
|
|
|
- if( children != null )
|
|
|
- {
|
|
|
- for( Object c : children )
|
|
|
- ((PseudoCodeNode)c).writeToStack( m );
|
|
|
- }
|
|
|
- function = true;
|
|
|
- switch( stepInto( m ) )
|
|
|
- {
|
|
|
- case BREAKPOINT:
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return CodeStatus.BREAKPOINT;
|
|
|
- case FINISHED:
|
|
|
- currentCodeLine = -1;
|
|
|
- switch( setSelected( true ) )
|
|
|
- {
|
|
|
- case SKIP:
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return forwardStepOverIntern( m );
|
|
|
- case STOP:
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return CodeStatus.BREAKPOINT;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- case UNFINISHED:
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return CodeStatus.UNFINISHED;
|
|
|
- }
|
|
|
- case ControlFlow.STEP_OVER:
|
|
|
- if( function )
|
|
|
- {
|
|
|
- m.addFrame( tmp ); // add old stack frame
|
|
|
- if( children != null )
|
|
|
- {
|
|
|
- for( Object c : children )
|
|
|
- ((PseudoCodeNode)c).loadFromStack( m );
|
|
|
- }
|
|
|
- m.removeFrame(); // remove the stack frame
|
|
|
- setSelected( false );
|
|
|
- }
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return CodeStatus.FINISHED;
|
|
|
- case ControlFlow.CALL:
|
|
|
- alg.addActiveFunction( cf.getFunction() );
|
|
|
- m.declare( "node_" + nodeId + "_call", cf.getFunction(), MemoryType.LOCAL );
|
|
|
- setSelected( false );
|
|
|
- m.declare( "callback", this, MemoryType.GLOBAL );
|
|
|
- switch( cf.getFunction().setSelected( true ) )
|
|
|
- {
|
|
|
- case CONTINUE:
|
|
|
- break;
|
|
|
- case SKIP:
|
|
|
- switch( cf.getFunction().forwardStepOverIntern( m ) )
|
|
|
- {
|
|
|
- case BREAKPOINT:
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return CodeStatus.BREAKPOINT;
|
|
|
- case FINISHED:
|
|
|
- setSelected( true );
|
|
|
- case UNFINISHED:
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return CodeStatus.UNFINISHED;
|
|
|
- }
|
|
|
- break;
|
|
|
- case STOP:
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return CodeStatus.BREAKPOINT;
|
|
|
- }
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return CodeStatus.UNFINISHED;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- m.undeclare( "node_" + nodeId + "_call", MemoryType.LOCAL );
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return CodeStatus.FINISHED;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if( children == null || children.size() <= currentCodeLine )
|
|
|
- {
|
|
|
- throw new IllegalStateException( "Some wired stuff is going on" );
|
|
|
- }
|
|
|
- switch( ( (PseudoCodeNode)children.get( currentCodeLine ) ).forwardStep( m ) )
|
|
|
- {
|
|
|
- case BREAKPOINT:
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return CodeStatus.BREAKPOINT;
|
|
|
- case FINISHED:
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return childNodeFinished( m );
|
|
|
- case UNFINISHED:
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return CodeStatus.UNFINISHED;
|
|
|
- }
|
|
|
- }
|
|
|
- hiddenActionWithoutSideEffects( m );
|
|
|
- return CodeStatus.UNFINISHED;
|
|
|
- }
|
|
|
-
|
|
|
- private CodeStatus childNodeFinished( Memory m )
|
|
|
- {
|
|
|
- ( (PseudoCodeNode)children.get( currentCodeLine ) ).setSelected( false );
|
|
|
- currentCodeLine++;
|
|
|
- if( children.size() <= currentCodeLine )
|
|
|
- {
|
|
|
- currentCodeLine = -1;
|
|
|
- switch( setSelected( true ) )
|
|
|
- {
|
|
|
- case SKIP:
|
|
|
- return forwardStepOverIntern( m );
|
|
|
- case STOP:
|
|
|
- return CodeStatus.BREAKPOINT;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- CodeStatus status = selectChild( currentCodeLine, m );
|
|
|
- if( status == CodeStatus.FINISHED )
|
|
|
- {
|
|
|
- currentCodeLine = -1;
|
|
|
- status = CodeStatus.UNFINISHED;
|
|
|
- switch( setSelected( true ) )
|
|
|
- {
|
|
|
- case SKIP:
|
|
|
- return forwardStepOverIntern( m );
|
|
|
- case STOP:
|
|
|
- return CodeStatus.BREAKPOINT;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- return status;
|
|
|
- }
|
|
|
- return CodeStatus.UNFINISHED;
|
|
|
- }
|
|
|
-
|
|
|
- private CodeStatus selectChild( int index, Memory m )
|
|
|
- {
|
|
|
- switch( ( (PseudoCodeNode)children.get( index ) ).setSelected( true ) )
|
|
|
- {
|
|
|
- case CONTINUE:
|
|
|
- return CodeStatus.UNFINISHED;
|
|
|
- case SKIP:
|
|
|
- switch( ( (PseudoCodeNode)children.get( index ) ).forwardStepOverIntern( m ) )
|
|
|
- {
|
|
|
- case BREAKPOINT:
|
|
|
- return CodeStatus.BREAKPOINT;
|
|
|
- case FINISHED:
|
|
|
- return childNodeFinished( m );
|
|
|
- case UNFINISHED:
|
|
|
- throw new IllegalStateException( "Skipping a node returned UNFINISHED" );
|
|
|
- }
|
|
|
- case STOP:
|
|
|
- return CodeStatus.BREAKPOINT;
|
|
|
- }
|
|
|
- return CodeStatus.UNFINISHED;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Perform steps until the next line of code on the same level of indentation as this line
|
|
|
- * is reached. Stops at the end of the program.
|
|
|
- * @return whether the whole stage is finished (afterwards).
|
|
|
- * For example if all steps are finished, then {@code FINISHED} is returned.
|
|
|
- */
|
|
|
- public CodeStatus forwardStepOver( Memory m )
|
|
|
- {
|
|
|
- switch( getForwardNode().forwardStepOverIntern( m ) )
|
|
|
- {
|
|
|
- case BREAKPOINT:
|
|
|
- return CodeStatus.BREAKPOINT;
|
|
|
- case FINISHED:
|
|
|
- if( getForwardNode() == this )
|
|
|
- return CodeStatus.FINISHED;
|
|
|
- else
|
|
|
- return childNodeFinished( m );
|
|
|
- case UNFINISHED:
|
|
|
- return CodeStatus.UNFINISHED;
|
|
|
- }
|
|
|
- return CodeStatus.UNFINISHED;
|
|
|
- }
|
|
|
-
|
|
|
- private CodeStatus forwardStepOverIntern( Memory m )
|
|
|
- {
|
|
|
- CodeStatus status = null;
|
|
|
- do {
|
|
|
- PseudoCodeNode af = alg.getActiveFunction();
|
|
|
- status = forwardStep( m );
|
|
|
- if( status == CodeStatus.UNFINISHED && af != alg.getActiveFunction() )
|
|
|
- {
|
|
|
- switch( alg.getActiveFunction().forwardStepOverIntern( m ) )
|
|
|
- {
|
|
|
- case BREAKPOINT:
|
|
|
- return CodeStatus.BREAKPOINT;
|
|
|
- case FINISHED:
|
|
|
- break;
|
|
|
- case UNFINISHED:
|
|
|
- throw new IllegalStateException( "StepOver did not return finished" );
|
|
|
- }
|
|
|
- }
|
|
|
- } while( status == CodeStatus.UNFINISHED );
|
|
|
- return status;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Perform steps until the next line of code on the level of indentation above this lines
|
|
|
- * level is reached. Stops at the end of the program.
|
|
|
- * @return whether the whole stage is finished (afterwards).
|
|
|
- * For example if all steps are finished, then {@code FINISHED} is returned.
|
|
|
- */
|
|
|
- public CodeStatus forwardStepOut( Memory m )
|
|
|
- {
|
|
|
- switch( getForwardNode().forwardStepOutIntern( m ) )
|
|
|
- {
|
|
|
- case BREAKPOINT:
|
|
|
- return CodeStatus.BREAKPOINT;
|
|
|
- case FINISHED:
|
|
|
- if( getForwardNode() == this )
|
|
|
- return CodeStatus.FINISHED;
|
|
|
- else
|
|
|
- return childNodeFinished( m );
|
|
|
- case UNFINISHED:
|
|
|
- return CodeStatus.UNFINISHED;
|
|
|
- }
|
|
|
- return CodeStatus.UNFINISHED;
|
|
|
- }
|
|
|
-
|
|
|
- private CodeStatus forwardStepOutIntern( Memory m )
|
|
|
+ public ControlFlow forwardStep( Memory m )
|
|
|
{
|
|
|
- if( parent != null && !alg.isActiveFunction( this ) )
|
|
|
- return ((PseudoCodeNode)parent).forwardStepOverIntern( m );
|
|
|
- return forwardStepOverIntern( m );
|
|
|
+ return code.runForward( m );
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Undo one atomic step of the algorithm. Stops at the beginning of the program.
|
|
|
- * @return whether the whole stage is finished in backwards direction (afterwards).
|
|
|
- * For example if all steps have been reverted, then {@code FINISHED} is returned.
|
|
|
- */
|
|
|
- public CodeStatus backwardStep( Memory m )
|
|
|
+ public ControlFlow backwardStep( Memory m )
|
|
|
{
|
|
|
- // TODO
|
|
|
- return null;
|
|
|
+ return code.runBackward( m );
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * Perform backward steps until the previous line of code on the same level of indentation
|
|
|
- * as this line is reached. Stops at the end of the program.
|
|
|
- * @return whether the whole stage is finished in backwards direction (afterwards).
|
|
|
- * For example if all steps have been reverted, then {@code FINISHED} is returned.
|
|
|
- */
|
|
|
- public CodeStatus backwardStepOver( Memory m )
|
|
|
- {
|
|
|
- return getBackwardNode().backwardStepOverIntern( m );
|
|
|
- }
|
|
|
-
|
|
|
- private CodeStatus backwardStepOverIntern( Memory m )
|
|
|
- {
|
|
|
- CodeStatus status = null;
|
|
|
- do {
|
|
|
- status = backwardStep( m );
|
|
|
- } while( status == CodeStatus.UNFINISHED );
|
|
|
- return status;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * Perform backward steps until the previous line of code on the level of indentation above
|
|
|
- * this lines level is reached. Stops at the end of the program.
|
|
|
- * @return whether the whole stage is finished in backwards direction (afterwards).
|
|
|
- * For example if all steps have been reverted, then {@code FINISHED} is returned.
|
|
|
- */
|
|
|
- public CodeStatus backwardStepOut( Memory m )
|
|
|
- {
|
|
|
- return getBackwardNode().backwardStepOutIntern( m );
|
|
|
- }
|
|
|
-
|
|
|
- private CodeStatus backwardStepOutIntern( Memory m )
|
|
|
- {
|
|
|
- if( parent != null )
|
|
|
- return ((PseudoCodeNode)parent).backwardStepOver( m );
|
|
|
- return backwardStepOutIntern( m );
|
|
|
- }
|
|
|
-
|
|
|
- protected void hiddenActionWithoutSideEffects( Memory m ) {}
|
|
|
}
|