ForEachLoop.java 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package codeline;
  2. import java.util.List;
  3. import processor.ControlFlow;
  4. import processor.Memory;
  5. import processor.StackFrame;
  6. import processor.Memory.ReadOnlyMemory;
  7. import processor.Memory.Visibility;
  8. import processor.StackFrame.FrameType;
  9. /**
  10. * the initial line of a for-each loop
  11. * @author kolja
  12. *
  13. * @param <T> the type of the iteration variable
  14. */
  15. public abstract class ForEachLoop <T> extends CodeLine {
  16. private String loopVar;
  17. public ForEachLoop( String varName )
  18. {
  19. this.loopVar = varName;
  20. }
  21. @Override
  22. public ControlFlow runForward(Memory m) {
  23. boolean declared = false; // prove if it is the first step in the loop
  24. if( !m.isSomewhereDefined( "line_" + lineId + "_index", Visibility.LOCAL ) )
  25. { // first loop step
  26. m.declare( "line_" + lineId + "_index", 0, Visibility.LOCAL );
  27. declared = true;
  28. }
  29. if( m.<Integer>read( "line_" + lineId + "_index", Visibility.LOCAL ) > list( m.createReadOnlyMemory() ).size() - 1 ) // prove if the loop has finished
  30. {
  31. actions.push( (Memory mem) -> {});
  32. return new ControlFlow( ControlFlow.STEP_OVER ); // don't execute the loop body
  33. }
  34. if( declared )
  35. {
  36. m.addFrame( new StackFrame( FrameType.LOOP ) );
  37. m.declare( loopVar, list( m.createReadOnlyMemory() ).get( m.read( "line_" + lineId + "_index", Visibility.LOCAL ) ), Visibility.LOCAL ); // set loop variable
  38. actions.push( (Memory mem) -> {
  39. mem.removeFrame();
  40. mem.undeclare( "line_" + lineId + "_index", Visibility.LOCAL );
  41. } );
  42. }
  43. else
  44. {
  45. int oldIndex = m.<Integer>read( "line_" + lineId + "_index", Visibility.LOCAL );
  46. m.write( "line_" + lineId + "_index", oldIndex + 1, Visibility.LOCAL ); // count index down
  47. if( m.<Integer>read( "line_" + lineId + "_index", Visibility.LOCAL ) > list( m.createReadOnlyMemory() ).size() - 1 ) // prove if loop was finished
  48. {
  49. StackFrame sf = m.removeFrame(); // remove loop stack
  50. actions.push( (Memory mem) -> {
  51. mem.write( "line_" + lineId + "_index", oldIndex, Visibility.LOCAL );
  52. mem.addFrame( sf ); // restore last loop stack
  53. });
  54. return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop
  55. }
  56. StackFrame old = m.removeFrame(); // fresh stack frame for loop body
  57. m.addFrame( new StackFrame( FrameType.LOOP ) );
  58. m.declare( loopVar, list( m.createReadOnlyMemory() ).get( m.read( "line_" + lineId + "_index", Visibility.LOCAL ) ), Visibility.LOCAL ); // update loop variable
  59. actions.push( (Memory mem) -> {
  60. mem.removeFrame();
  61. mem.addFrame( old );
  62. mem.write( "line_" + lineId + "_index", oldIndex, Visibility.LOCAL );
  63. });
  64. }
  65. return new ControlFlow( ControlFlow.STEP_INTO );
  66. }
  67. /**
  68. * returns the list which the loop iterates through
  69. * @param m the memory in which the variables are stored
  70. * @return the list
  71. */
  72. protected abstract List<T> list( ReadOnlyMemory m );
  73. }