PseudoCodeProcessor.java 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. package processor;
  2. import java.util.Stack;
  3. import processor.Memory.Visibility;
  4. import processor.StackFrame.FrameType;
  5. public class PseudoCodeProcessor {
  6. public static enum CodeStatus
  7. {
  8. UNFINISHED,
  9. BREAKPOINT,
  10. FINISHED
  11. }
  12. private String currentDebugOutput;
  13. private Memory mem;
  14. private PseudoCodeNode programPointer;
  15. private Stack<ControlFlow> controlStack;
  16. private boolean skip = false;
  17. public PseudoCodeProcessor( PseudoCodeNode start )
  18. {
  19. mem = new Memory();
  20. mem.addFrame( new StackFrame( FrameType.FUNCTION ) );
  21. programPointer = start;
  22. currentDebugOutput = "";
  23. controlStack = new Stack<>();
  24. }
  25. private CodeStatus selectNextNode( PseudoCodeNode next, PseudoCodeNode last )
  26. {
  27. programPointer = next;
  28. last.setSelected( false );
  29. switch( next.setSelected( true ) )
  30. {
  31. case CONTINUE:
  32. skip = false;
  33. return CodeStatus.UNFINISHED;
  34. case SKIP:
  35. return forwardStepOverUntilNotSkip();
  36. case STOP:
  37. return CodeStatus.BREAKPOINT;
  38. }
  39. return CodeStatus.UNFINISHED;
  40. }
  41. public CodeStatus forwardStep()
  42. {
  43. if( programPointer == null )
  44. return CodeStatus.FINISHED;
  45. StackFrame before = mem.removeFrame();
  46. mem.addFrame( before );
  47. ControlFlow cf = null;
  48. if( mem.isDefined( "_call" + programPointer.getId(), Visibility.LOCAL ) )
  49. {
  50. String name = "_call" + programPointer.getId();
  51. mem.undeclare( name, Visibility.LOCAL );
  52. cf = programPointer.emptyForwardStep( mem );
  53. cf.setBackwardAction( (Memory m) -> {
  54. mem.declare( name, true, Visibility.LOCAL );
  55. });
  56. }
  57. else
  58. cf = programPointer.forwardStep( mem );
  59. controlStack.push( cf );
  60. currentDebugOutput = programPointer.getDebugOutput( mem );
  61. switch( cf.getStatus() )
  62. {
  63. case ControlFlow.STEP_INTO:
  64. if( mem.isDefined( "_returnTo" + programPointer.getId(), Visibility.GLOBAL ) )
  65. {
  66. String name = "_returnTo" + programPointer.getId();
  67. mem.declare( name, mem.read( name, Visibility.GLOBAL ), Visibility.LOCAL );
  68. mem.undeclare( name, Visibility.GLOBAL );
  69. cf.setBackwardAction( (Memory m) -> {
  70. mem.declare( name, mem.read( name, Visibility.LOCAL ), Visibility.GLOBAL );
  71. mem.undeclare( name, Visibility.LOCAL );
  72. });
  73. }
  74. if( programPointer.getChildCount() == 0 )
  75. throw new IllegalStateException( "A Codeline without sublines tried to make a STEP_INTO." );
  76. else
  77. return selectNextNode( (PseudoCodeNode)programPointer.getFirstChild(), programPointer );
  78. case ControlFlow.STEP_OVER:
  79. if( programPointer.getParent() == null )
  80. return CodeStatus.FINISHED;
  81. if( before.isDefined( "_returnTo" + programPointer.getId() ) )
  82. {
  83. String name = "_returnTo" + programPointer.getId();
  84. PseudoCodeNode nextPC = before.<PseudoCodeNode>get( name );
  85. before.undeclare( name );
  86. cf.setBackwardAction( (Memory m) -> {
  87. before.declare( name, nextPC );
  88. });
  89. return selectNextNode( nextPC, programPointer );
  90. }
  91. PseudoCodeNode nextPC = (PseudoCodeNode) ((PseudoCodeNode)programPointer.getParent()).getChildAfter( programPointer );
  92. if( nextPC == null )
  93. return selectNextNode( (PseudoCodeNode)programPointer.getParent(), programPointer );
  94. else
  95. return selectNextNode( nextPC, programPointer );
  96. case ControlFlow.CALL:
  97. PseudoCodeNode f = cf.getFunction();
  98. String name = "_call" + programPointer.getId();
  99. mem.declare( name, true, Visibility.LOCAL );
  100. mem.declare( "_returnTo" + f.getId(), cf.getJumpBack(), Visibility.GLOBAL );
  101. cf.setBackwardAction( (Memory m) -> {
  102. m.undeclare( "_returnTo" + f.getId(), Visibility.GLOBAL );
  103. m.undeclare( name, Visibility.LOCAL );
  104. });
  105. return selectNextNode( f, programPointer );
  106. }
  107. throw new IllegalStateException( "Unknown ControlFlow action" );
  108. }
  109. private CodeStatus forwardStepOverUntilNotSkip() {
  110. skip = true;
  111. if( programPointer == null )
  112. return CodeStatus.FINISHED;
  113. int stackSize = mem.getSize();
  114. CodeStatus status = CodeStatus.UNFINISHED;
  115. do {
  116. status = forwardStep();
  117. } while( mem.getSize() > stackSize && status == CodeStatus.UNFINISHED && skip );
  118. return status;
  119. }
  120. public CodeStatus forwardStepOver()
  121. {
  122. if( programPointer == null )
  123. return CodeStatus.FINISHED;
  124. int stackSize = mem.getSize();
  125. CodeStatus status = CodeStatus.UNFINISHED;
  126. do {
  127. status = forwardStep();
  128. } while( mem.getSize() > stackSize && status == CodeStatus.UNFINISHED );
  129. return status;
  130. }
  131. public CodeStatus forwardStepOut()
  132. {
  133. if( programPointer == null )
  134. return CodeStatus.FINISHED;
  135. int stackSize = mem.getSize();
  136. CodeStatus status = CodeStatus.UNFINISHED;
  137. do {
  138. status = forwardStep();
  139. } while( mem.getSize() >= stackSize && status == CodeStatus.UNFINISHED );
  140. return status;
  141. }
  142. private CodeStatus selectBeforeNode( PseudoCodeNode next, PseudoCodeNode last )
  143. {
  144. programPointer = next;
  145. last.setSelected( false );
  146. switch( next.setSelected( true ) )
  147. {
  148. case CONTINUE:
  149. skip = false;
  150. return CodeStatus.UNFINISHED;
  151. case SKIP:
  152. return backwardStepOverUntilNotSkip();
  153. case STOP:
  154. return CodeStatus.BREAKPOINT;
  155. }
  156. return CodeStatus.UNFINISHED;
  157. }
  158. public CodeStatus backwardStep()
  159. {
  160. if( programPointer == null || controlStack.isEmpty() )
  161. return CodeStatus.FINISHED;
  162. ControlFlow cf = controlStack.pop();
  163. PseudoCodeNode nextPC = cf.getJumpBack();
  164. cf.backward( mem );
  165. nextPC.backwardStep( mem );
  166. currentDebugOutput = nextPC.getDebugOutput( mem );
  167. return selectBeforeNode( nextPC, programPointer );
  168. }
  169. public CodeStatus backwardStepOverUntilNotSkip()
  170. {
  171. skip = true;
  172. if( programPointer == null )
  173. return CodeStatus.FINISHED;
  174. int stackSize = mem.getSize();
  175. CodeStatus status = CodeStatus.UNFINISHED;
  176. do {
  177. status = backwardStep();
  178. } while( mem.getSize() > stackSize && status == CodeStatus.UNFINISHED && skip );
  179. return status;
  180. }
  181. public CodeStatus backwardStepOver()
  182. {
  183. if( programPointer == null )
  184. return CodeStatus.FINISHED;
  185. int stackSize = mem.getSize();
  186. CodeStatus status = CodeStatus.UNFINISHED;
  187. do {
  188. status = backwardStep();
  189. } while( mem.getSize() > stackSize && status == CodeStatus.UNFINISHED );
  190. return status;
  191. }
  192. public CodeStatus backwardStepOut()
  193. {
  194. if( programPointer == null )
  195. return CodeStatus.FINISHED;
  196. int stackSize = mem.getSize();
  197. CodeStatus status = CodeStatus.UNFINISHED;
  198. do {
  199. status = backwardStep();
  200. } while( mem.getSize() >= stackSize && status == CodeStatus.UNFINISHED );
  201. return status;
  202. }
  203. public Memory getMemory()
  204. {
  205. return mem;
  206. }
  207. public String getDebugOutput()
  208. {
  209. return currentDebugOutput;
  210. }
  211. }