1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- package codeline;
- import java.util.List;
- import processor.ControlFlow;
- import processor.Memory;
- import processor.StackFrame;
- import processor.Memory.ReadOnlyMemory;
- import processor.Memory.Visibility;
- import processor.StackFrame.FrameType;
- /**
- * the initial line of a for-each loop
- * @author kolja
- *
- * @param <T> the type of the iteration variable
- */
- public abstract class ForEachLoop <T> extends CodeLine {
- private String loopVar;
-
- public ForEachLoop( String varName )
- {
- this.loopVar = varName;
- }
-
- @Override
- public ControlFlow runForward(Memory m) {
- boolean declared = false; // prove if it is the first step in the loop
- if( !m.isSomewhereDefined( "line_" + lineId + "_index", Visibility.LOCAL ) )
- { // first loop step
- m.declare( "line_" + lineId + "_index", 0, Visibility.LOCAL );
- declared = true;
- }
- if( m.<Integer>read( "line_" + lineId + "_index", Visibility.LOCAL ) > list( m.createReadOnlyMemory() ).size() - 1 ) // prove if the loop has finished
- {
- actions.push( (Memory mem) -> {});
- return new ControlFlow( ControlFlow.STEP_OVER ); // don't execute the loop body
- }
- if( declared )
- {
- m.addFrame( new StackFrame( FrameType.LOOP ) );
- m.declare( loopVar, list( m.createReadOnlyMemory() ).get( m.read( "line_" + lineId + "_index", Visibility.LOCAL ) ), Visibility.LOCAL ); // set loop variable
- actions.push( (Memory mem) -> {
- mem.removeFrame();
- mem.undeclare( "line_" + lineId + "_index", Visibility.LOCAL );
- } );
- }
- else
- {
- int oldIndex = m.<Integer>read( "line_" + lineId + "_index", Visibility.LOCAL );
- m.write( "line_" + lineId + "_index", oldIndex + 1, Visibility.LOCAL ); // count index down
- if( m.<Integer>read( "line_" + lineId + "_index", Visibility.LOCAL ) > list( m.createReadOnlyMemory() ).size() - 1 ) // prove if loop was finished
- {
- StackFrame sf = m.removeFrame(); // remove loop stack
- actions.push( (Memory mem) -> {
- mem.write( "line_" + lineId + "_index", oldIndex, Visibility.LOCAL );
- mem.addFrame( sf ); // restore last loop stack
- });
- return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop
- }
- StackFrame old = m.removeFrame(); // fresh stack frame for loop body
- m.addFrame( new StackFrame( FrameType.LOOP ) );
- m.declare( loopVar, list( m.createReadOnlyMemory() ).get( m.read( "line_" + lineId + "_index", Visibility.LOCAL ) ), Visibility.LOCAL ); // update loop variable
- actions.push( (Memory mem) -> {
- mem.removeFrame();
- mem.addFrame( old );
- mem.write( "line_" + lineId + "_index", oldIndex, Visibility.LOCAL );
- });
- }
- return new ControlFlow( ControlFlow.STEP_INTO );
- }
-
- /**
- * returns the list which the loop iterates through
- * @param m the memory in which the variables are stored
- * @return the list
- */
- protected abstract List<T> list( ReadOnlyMemory m );
- }
|