iter.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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.current >= self.r.stop) return 0;
  8. vm->s_data.emplace(VM::tp_int, self.current);
  9. self.current += self.r.step;
  10. return 1;
  11. });
  12. }
  13. void RangeIterR::_register(VM* vm, PyVar mod, PyVar type){
  14. vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
  15. vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
  16. RangeIterR& self = PK_OBJ_GET(RangeIterR, _0);
  17. if(self.current <= self.r.stop) return 0;
  18. vm->s_data.emplace(VM::tp_int, self.current);
  19. self.current += self.r.step;
  20. return 1;
  21. });
  22. }
  23. void ArrayIter::_register(VM* vm, PyVar mod, PyVar type){
  24. vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
  25. vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
  26. ArrayIter& self = _CAST(ArrayIter&, _0);
  27. if(self.current == self.end) return 0;
  28. vm->s_data.push(*self.current++);
  29. return 1;
  30. });
  31. }
  32. void StringIter::_register(VM* vm, PyVar mod, PyVar type){
  33. vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
  34. vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
  35. StringIter& self = _CAST(StringIter&, _0);
  36. Str& s = PK_OBJ_GET(Str, self.ref);
  37. if(self.i == s.size) return 0;
  38. int start = self.i;
  39. int len = utf8len(s.data[self.i]);
  40. self.i += len;
  41. vm->s_data.push(VAR(s.substr(start, len)));
  42. return 1;
  43. });
  44. }
  45. PyVar Generator::next(VM* vm){
  46. if(state == 2) return vm->StopIteration;
  47. // reset frame._sp_base
  48. lf->frame._sp_base = vm->s_data._sp;
  49. lf->frame._locals.a = vm->s_data._sp;
  50. // restore the context
  51. for(PyVar obj: s_backup) vm->s_data.push(obj);
  52. // relocate stack objects (their addresses become invalid)
  53. for(PyVar* p=lf->frame.actual_sp_base(); p!=vm->s_data.end(); p++){
  54. if(p->type == VM::tp_stack_memory){
  55. // TODO: refactor this
  56. int count = p->as<StackMemory>().count;
  57. if(count < 0){
  58. void* new_p = p + count;
  59. p[1]._1 = reinterpret_cast<i64>(new_p);
  60. }
  61. }
  62. }
  63. s_backup.clear();
  64. vm->callstack.pushx(lf);
  65. lf = nullptr;
  66. PyVar ret;
  67. try{
  68. ret = vm->__run_top_frame();
  69. }catch(...){
  70. state = 2; // end this generator immediately when an exception is thrown
  71. throw;
  72. }
  73. if(ret == PY_OP_YIELD){
  74. // backup the context
  75. lf = vm->callstack.popx();
  76. ret = vm->s_data.popx();
  77. for(PyVar obj: lf->frame.stack_view(&vm->s_data)) s_backup.push_back(obj);
  78. vm->s_data.reset(lf->frame._sp_base);
  79. // TODO: should we add this snippet here?
  80. // #if PK_ENABLE_PROFILER
  81. // if(!_next_breakpoint.empty() && callstack.size()<_next_breakpoint.callstack_size){
  82. // _next_breakpoint = NextBreakpoint();
  83. // }
  84. // #endif
  85. state = 1;
  86. if(ret == vm->StopIteration) state = 2;
  87. return ret;
  88. }else{
  89. state = 2;
  90. return vm->StopIteration;
  91. }
  92. }
  93. void Generator::_register(VM* vm, PyVar mod, PyVar type){
  94. vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
  95. vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
  96. Generator& self = _CAST(Generator&, _0);
  97. PyVar retval = self.next(vm);
  98. if(retval == vm->StopIteration) return 0;
  99. vm->s_data.push(retval);
  100. return 1;
  101. });
  102. }
  103. void DictItemsIter::_register(VM *vm, PyVar mod, PyVar type){
  104. vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
  105. vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
  106. DictItemsIter& self = _CAST(DictItemsIter&, _0);
  107. Dict& d = PK_OBJ_GET(Dict, self.ref);
  108. if(self.i == -1) return 0;
  109. vm->s_data.push(d._items[self.i].first);
  110. vm->s_data.push(d._items[self.i].second);
  111. self.i = d._nodes[self.i].next;
  112. return 2;
  113. });
  114. }
  115. PyVar VM::__py_generator(LinkedFrame* frame, ArgsView buffer){
  116. return vm->new_user_object<Generator>(std::move(frame), buffer);
  117. }
  118. } // namespace pkpy