iter.h 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #pragma once
  2. #include "ceval.h"
  3. namespace pkpy{
  4. class RangeIter : public BaseIter {
  5. i64 current;
  6. Range r;
  7. public:
  8. RangeIter(VM* vm, PyVar _ref) : BaseIter(vm, _ref) {
  9. this->r = OBJ_GET(Range, _ref);
  10. this->current = r.start;
  11. }
  12. inline bool _has_next(){
  13. return r.step > 0 ? current < r.stop : current > r.stop;
  14. }
  15. PyVar next(){
  16. if(!_has_next()) return nullptr;
  17. current += r.step;
  18. return VAR(current-r.step);
  19. }
  20. };
  21. template <typename T>
  22. class ArrayIter : public BaseIter {
  23. size_t index = 0;
  24. const T* p;
  25. public:
  26. ArrayIter(VM* vm, PyVar _ref) : BaseIter(vm, _ref) { p = &OBJ_GET(T, _ref);}
  27. PyVar next(){
  28. if(index == p->size()) return nullptr;
  29. return p->operator[](index++);
  30. }
  31. };
  32. class StringIter : public BaseIter {
  33. int index = 0;
  34. Str* str;
  35. public:
  36. StringIter(VM* vm, PyVar _ref) : BaseIter(vm, _ref) {
  37. str = &OBJ_GET(Str, _ref);
  38. }
  39. PyVar next() {
  40. if(index == str->u8_length()) return nullptr;
  41. return VAR(str->u8_getitem(index++));
  42. }
  43. };
  44. PyVar Generator::next(){
  45. if(state == 2) return nullptr;
  46. vm->callstack.push(std::move(frame));
  47. PyVar ret = vm->_exec();
  48. if(ret == vm->_py_op_yield){
  49. frame = std::move(vm->callstack.top());
  50. vm->callstack.pop();
  51. state = 1;
  52. return frame->pop_value(vm);
  53. }else{
  54. state = 2;
  55. return nullptr;
  56. }
  57. }
  58. } // namespace pkpy