repl.h 2.0 KB

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