frame.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #include "pocketpy/objects/stackmemory.hpp"
  2. #include "pocketpy/interpreter/frame.hpp"
  3. #include <stdexcept>
  4. namespace pkpy{
  5. PyVar* FastLocals::try_get_name(StrName name){
  6. int index = co->varnames_inv.try_get(name);
  7. if(index == -1) return nullptr;
  8. return &a[index];
  9. }
  10. NameDict_ FastLocals::to_namedict(){
  11. NameDict_ dict = std::make_shared<NameDict>();
  12. co->varnames_inv.apply([&](StrName name, int index){
  13. PyVar value = a[index];
  14. if(value) dict->set(name, value);
  15. });
  16. return dict;
  17. }
  18. PyVar* Frame::f_closure_try_get(StrName name){
  19. if(_callable == nullptr) return nullptr;
  20. Function& fn = _callable->as<Function>();
  21. if(fn._closure == nullptr) return nullptr;
  22. return fn._closure->try_get_2(name);
  23. }
  24. int Frame::prepare_jump_exception_handler(ValueStack* _s){
  25. // try to find a parent try block
  26. int i = co->lines[ip()].iblock;
  27. while(i >= 0){
  28. if(co->blocks[i].type == CodeBlockType::TRY_EXCEPT) break;
  29. i = co->blocks[i].parent;
  30. }
  31. if(i < 0) return -1;
  32. PyVar obj = _s->popx(); // pop exception object
  33. UnwindTarget* uw = find_unwind_target(i);
  34. _s->reset(actual_sp_base() + uw->offset); // unwind the stack
  35. _s->push(obj); // push it back
  36. return co->blocks[i].end;
  37. }
  38. int Frame::_exit_block(ValueStack* _s, int i){
  39. auto type = co->blocks[i].type;
  40. if(type == CodeBlockType::FOR_LOOP){
  41. _s->pop(); // pop the iterator
  42. // pop possible stack memory slots
  43. if(_s->top().type == kTpStackMemoryIndex){
  44. int count = _s->top().as<StackMemory>().count;
  45. assert(count < 0);
  46. _s->_sp += count;
  47. _s->_sp -= 2; // pop header and tail
  48. }
  49. }else if(type==CodeBlockType::CONTEXT_MANAGER){
  50. _s->pop();
  51. }
  52. return co->blocks[i].parent;
  53. }
  54. void Frame::prepare_jump_break(ValueStack* _s, int target){
  55. int i = co->lines[ip()].iblock;
  56. if(target >= co->codes.size()){
  57. while(i>=0) i = _exit_block(_s, i);
  58. }else{
  59. // BUG (solved)
  60. // for i in range(4):
  61. // _ = 0
  62. // # if there is no op here, the block check will fail
  63. // while i: --i
  64. int next_block = co->lines[target].iblock;
  65. while(i>=0 && i!=next_block) i = _exit_block(_s, i);
  66. if(i!=next_block) throw std::runtime_error("invalid jump");
  67. }
  68. }
  69. void Frame::set_unwind_target(PyVar* _sp){
  70. int iblock = co->lines[ip()].iblock;
  71. UnwindTarget* existing = find_unwind_target(iblock);
  72. if(existing){
  73. existing->offset = _sp - actual_sp_base();
  74. }else{
  75. UnwindTarget* prev = _uw_list;
  76. _uw_list = new UnwindTarget(iblock, _sp - actual_sp_base());
  77. _uw_list->next = prev;
  78. }
  79. }
  80. UnwindTarget* Frame::find_unwind_target(int iblock){
  81. UnwindTarget* p;
  82. for(p=_uw_list; p!=nullptr; p=p->next){
  83. if(p->iblock == iblock) return p;
  84. }
  85. return nullptr;
  86. }
  87. Frame::~Frame(){
  88. while(_uw_list != nullptr){
  89. UnwindTarget* p = _uw_list;
  90. _uw_list = p->next;
  91. delete p;
  92. }
  93. }
  94. void CallStack::pop(){
  95. assert(!empty());
  96. LinkedFrame* p = _tail;
  97. _tail = p->f_back;
  98. p->~LinkedFrame();
  99. PoolFrame_dealloc(p);
  100. --_size;
  101. }
  102. LinkedFrame* CallStack::popx(){
  103. assert(!empty());
  104. LinkedFrame* p = _tail;
  105. _tail = p->f_back;
  106. --_size;
  107. p->f_back = nullptr; // unlink
  108. return p;
  109. }
  110. void CallStack::pushx(LinkedFrame* p){
  111. p->f_back = _tail;
  112. _tail = p;
  113. ++_size;
  114. }
  115. } // namespace pkpy