iter.cpp 3.6 KB

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