package codelines; import animation.CodeLine; import animation.ControlFlow; import animation.Memory; import animation.StackFrame; import animation.Memory.MemoryType; import animation.Memory.ReadOnlyMemory; import animation.StackFrame.FrameType; public abstract class AbstractForLoop extends CodeLine { String loopVar; public AbstractForLoop( String varName ) { this.loopVar = varName; } @Override public ControlFlow runForward(Memory m) { if( !m.isDefined( loopVar, MemoryType.LOCAL ) ) { // first loop step m.addFrame( new StackFrame( FrameType.LOOP ) ); m.declare( loopVar, begin( m.createReadOnlyMemory() ), MemoryType.LOCAL ); // set loop variable if( !condition( m.createReadOnlyMemory() ) ) // prove if the loop has finished { m.removeFrame(); actions.push( (Memory mem) -> {} ); return new ControlFlow( ControlFlow.STEP_OVER ); // don't execute the loop body } actions.push( (Memory mem) -> { mem.removeFrame(); } ); } T next = step( m.createReadOnlyMemory() ); T old = m.read( loopVar, MemoryType.LOCAL ); m.write( loopVar, next, MemoryType.LOCAL ); if( !condition( m.createReadOnlyMemory() ) ) // prove if loop was finished { StackFrame sf = m.removeFrame(); // remove loop stack actions.add( (Memory mem) -> { mem.addFrame( sf ); // restore last loop stack mem.write( loopVar, old, MemoryType.LOCAL ); }); return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop } StackFrame oldF = m.removeFrame(); // fresh stack frame for loop body m.addFrame( new StackFrame( FrameType.LOOP ) ); m.declare( loopVar, next, MemoryType.LOCAL ); actions.push( (Memory mem) -> { mem.removeFrame(); mem.addFrame( oldF ); mem.write( loopVar, old, MemoryType.LOCAL ); }); return new ControlFlow( ControlFlow.STEP_INTO ); } abstract protected T begin( ReadOnlyMemory m ); abstract protected T step( ReadOnlyMemory m ); abstract protected boolean condition( final ReadOnlyMemory m ); }