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 the type of the iteration variable */ public abstract class ForEachLoop 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.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.read( "line_" + lineId + "_index", Visibility.LOCAL ); m.write( "line_" + lineId + "_index", oldIndex + 1, Visibility.LOCAL ); // count index down if( m.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 list( ReadOnlyMemory m ); }