repl.h 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #pragma once
  2. #include "compiler.h"
  3. #include "vm.h"
  4. enum InputResult {
  5. NEED_MORE_LINES = 0,
  6. EXEC_DONE = 1,
  7. EXEC_SKIPPED = 2,
  8. };
  9. class REPL {
  10. protected:
  11. int need_more_lines = 0;
  12. std::string buffer;
  13. VM* vm;
  14. bool exited = false;
  15. void _exit(){
  16. exited = true;
  17. exit(0);
  18. }
  19. public:
  20. REPL(VM* vm) : vm(vm){
  21. (*vm->_stdout) << ("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ")\n");
  22. (*vm->_stdout) << ("https://github.com/blueloveTH/pocketpy" "\n");
  23. (*vm->_stdout) << ("Type \"exit()\" to exit." "\n");
  24. }
  25. bool is_need_more_lines() const {
  26. return need_more_lines;
  27. }
  28. InputResult input(std::string line){
  29. if(exited) return EXEC_SKIPPED;
  30. if(need_more_lines){
  31. buffer += line;
  32. buffer += '\n';
  33. int n = buffer.size();
  34. if(n>=need_more_lines){
  35. for(int i=buffer.size()-need_more_lines; i<buffer.size(); i++){
  36. if(buffer[i] != '\n') goto __NOT_ENOUGH_LINES;
  37. }
  38. need_more_lines = 0;
  39. line = buffer;
  40. buffer.clear();
  41. }else{
  42. __NOT_ENOUGH_LINES:
  43. return NEED_MORE_LINES;
  44. }
  45. }else{
  46. if(line == "exit()") _exit();
  47. if(line.empty()) return EXEC_SKIPPED;
  48. }
  49. try{
  50. _Code code = compile(vm, line.c_str(), "<stdin>", SINGLE_MODE);
  51. if(code == nullptr) return EXEC_SKIPPED;
  52. vm->execAsync(code);
  53. return EXEC_DONE;
  54. }catch(NeedMoreLines& ne){
  55. buffer += line;
  56. buffer += '\n';
  57. need_more_lines = ne.isClassDef ? 3 : 2;
  58. return NEED_MORE_LINES;
  59. }
  60. }
  61. };