repl.h 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. #pragma once
  2. #include "compiler.h"
  3. #include "vm.h"
  4. enum InputResult {
  5. NEED_MORE_LINES = 0,
  6. EXEC_STARTED = 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. public:
  15. REPL(VM* vm) : vm(vm){
  16. (*vm->_stdout) << ("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ")\n");
  17. (*vm->_stdout) << ("https://github.com/blueloveTH/pocketpy" "\n");
  18. (*vm->_stdout) << ("Type \"exit()\" to exit." "\n");
  19. }
  20. InputResult input(std::string line){
  21. if(need_more_lines){
  22. buffer += line;
  23. buffer += '\n';
  24. int n = buffer.size();
  25. if(n>=need_more_lines){
  26. for(int i=buffer.size()-need_more_lines; i<buffer.size(); i++){
  27. if(buffer[i] != '\n') goto __NOT_ENOUGH_LINES;
  28. }
  29. need_more_lines = 0;
  30. line = buffer;
  31. buffer.clear();
  32. }else{
  33. __NOT_ENOUGH_LINES:
  34. return NEED_MORE_LINES;
  35. }
  36. }else{
  37. if(line.empty()) return EXEC_SKIPPED;
  38. }
  39. try{
  40. vm->compile(line, "<stdin>", SINGLE_MODE);
  41. }catch(NeedMoreLines& ne){
  42. buffer += line;
  43. buffer += '\n';
  44. need_more_lines = ne.isClassDef ? 3 : 2;
  45. if (need_more_lines) return NEED_MORE_LINES;
  46. }catch(...){
  47. // do nothing
  48. }
  49. vm->exec(line, "<stdin>", SINGLE_MODE);
  50. return EXEC_STARTED;
  51. }
  52. };