frame.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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.get(name, -1);
  7. if(index == -1) return nullptr;
  8. return &a[index];
  9. }
  10. NameDict_ FastLocals::to_namedict() {
  11. NameDict_ dict = std::make_shared<NameDict>();
  12. for(auto [name, index]: co->varnames_inv){
  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)
  58. i = _exit_block(_s, i);
  59. } else {
  60. // BUG (solved)
  61. // for i in range(4):
  62. // _ = 0
  63. // # if there is no op here, the block check will fail
  64. // while i: --i
  65. int next_block = co->lines[target].iblock;
  66. while(i >= 0 && i != next_block)
  67. i = _exit_block(_s, i);
  68. if(i != next_block) throw std::runtime_error("invalid jump");
  69. }
  70. }
  71. void Frame::set_unwind_target(PyVar* _sp) {
  72. int iblock = co->lines[ip()].iblock;
  73. UnwindTarget* existing = find_unwind_target(iblock);
  74. if(existing) {
  75. existing->offset = _sp - actual_sp_base();
  76. } else {
  77. UnwindTarget* prev = _uw_list;
  78. _uw_list = new UnwindTarget(iblock, _sp - actual_sp_base());
  79. _uw_list->next = prev;
  80. }
  81. }
  82. UnwindTarget* Frame::find_unwind_target(int iblock) {
  83. UnwindTarget* p;
  84. for(p = _uw_list; p != nullptr; p = p->next) {
  85. if(p->iblock == iblock) return p;
  86. }
  87. return nullptr;
  88. }
  89. Frame::~Frame() {
  90. while(_uw_list != nullptr) {
  91. UnwindTarget* p = _uw_list;
  92. _uw_list = p->next;
  93. delete p;
  94. }
  95. }
  96. void CallStack::pop() {
  97. assert(!empty());
  98. LinkedFrame* p = _tail;
  99. _tail = p->f_back;
  100. p->~LinkedFrame();
  101. PoolFrame_dealloc(p);
  102. --_size;
  103. }
  104. LinkedFrame* CallStack::popx() {
  105. assert(!empty());
  106. LinkedFrame* p = _tail;
  107. _tail = p->f_back;
  108. --_size;
  109. p->f_back = nullptr; // unlink
  110. return p;
  111. }
  112. void CallStack::pushx(LinkedFrame* p) {
  113. p->f_back = _tail;
  114. _tail = p;
  115. ++_size;
  116. }
  117. } // namespace pkpy