iter.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #include "pocketpy/iter.h"
  2. namespace pkpy{
  3. void RangeIter::_register(VM* vm, PyVar mod, PyVar type){
  4. vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
  5. vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
  6. RangeIter& self = PK_OBJ_GET(RangeIter, _0);
  7. if(self.r.step > 0){
  8. if(self.current >= self.r.stop) return 0;
  9. }else{
  10. if(self.current <= self.r.stop) return 0;
  11. }
  12. vm->s_data.push(VAR(self.current));
  13. self.current += self.r.step;
  14. return 1;
  15. });
  16. }
  17. void ArrayIter::_register(VM* vm, PyVar mod, PyVar type){
  18. vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
  19. vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
  20. ArrayIter& self = _CAST(ArrayIter&, _0);
  21. if(self.current == self.end) return 0;
  22. vm->s_data.push(*self.current++);
  23. return 1;
  24. });
  25. }
  26. void StringIter::_register(VM* vm, PyVar mod, PyVar type){
  27. vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
  28. vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
  29. StringIter& self = _CAST(StringIter&, _0);
  30. Str& s = PK_OBJ_GET(Str, self.ref);
  31. if(self.i == s.size) return 0;
  32. int start = self.i;
  33. int len = utf8len(s.data[self.i]);
  34. self.i += len;
  35. vm->s_data.push(VAR(s.substr(start, len)));
  36. return 1;
  37. });
  38. }
  39. PyVar Generator::next(VM* vm){
  40. if(state == 2) return vm->StopIteration;
  41. // reset frame._sp_base
  42. frame._sp_base = vm->s_data._sp;
  43. frame._locals.a = vm->s_data._sp;
  44. // restore the context
  45. for(PyVar obj: s_backup) vm->s_data.push(obj);
  46. s_backup.clear();
  47. vm->callstack.emplace(std::move(frame));
  48. PyVar ret;
  49. try{
  50. ret = vm->__run_top_frame();
  51. }catch(...){
  52. state = 2; // end this generator immediately when an exception is thrown
  53. throw;
  54. }
  55. if(ret == PY_OP_YIELD){
  56. // backup the context
  57. frame = std::move(vm->callstack.top());
  58. ret = vm->s_data.popx();
  59. for(PyVar obj: frame.stack_view(&vm->s_data)) s_backup.push_back(obj);
  60. vm->__pop_frame();
  61. state = 1;
  62. if(ret == vm->StopIteration) state = 2;
  63. return ret;
  64. }else{
  65. state = 2;
  66. return vm->StopIteration;
  67. }
  68. }
  69. void Generator::_register(VM* vm, PyVar mod, PyVar type){
  70. vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
  71. vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
  72. Generator& self = _CAST(Generator&, _0);
  73. PyVar retval = self.next(vm);
  74. if(retval == vm->StopIteration) return 0;
  75. vm->s_data.push(retval);
  76. return 1;
  77. });
  78. }
  79. void DictItemsIter::_register(VM *vm, PyVar mod, PyVar type){
  80. vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
  81. vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
  82. DictItemsIter& self = _CAST(DictItemsIter&, _0);
  83. Dict& d = PK_OBJ_GET(Dict, self.ref);
  84. if(self.i == -1) return 0;
  85. vm->s_data.push(d._items[self.i].first);
  86. vm->s_data.push(d._items[self.i].second);
  87. self.i = d._nodes[self.i].next;
  88. return 2;
  89. });
  90. }
  91. PyVar VM::__py_generator(Frame&& frame, ArgsView buffer){
  92. return vm->new_user_object<Generator>(std::move(frame), buffer);
  93. }
  94. } // namespace pkpy