frame.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include "pocketpy/interpreter/frame.hpp"
  2. #include "pocketpy/common/smallmap.h"
  3. namespace pkpy {
  4. PyVar* FastLocals::try_get_name(StrName name) {
  5. int index = c11_smallmap_n2i__get(&co->varnames_inv, name.index, -1);
  6. if(index == -1) return nullptr;
  7. return &a[index];
  8. }
  9. NameDict* FastLocals::to_namedict() {
  10. NameDict* dict = new NameDict();
  11. for(int i=0; i<co->varnames_inv.count; i++){
  12. auto entry = c11__getitem(c11_smallmap_n2i_KV, &co->varnames_inv, i);
  13. PyVar value = a[entry.value];
  14. if(value) dict->set(StrName(entry.key), 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 = c11__at(BytecodeEx, &co->codes_ex, ip())->iblock;
  27. while(i >= 0) {
  28. CodeBlock* block = c11__at(CodeBlock, &co->blocks, i);
  29. if(block->type == CodeBlockType_TRY_EXCEPT) break;
  30. i = block->parent;
  31. }
  32. if(i < 0) return -1;
  33. PyVar obj = _s->popx(); // pop exception object
  34. UnwindTarget* uw = find_unwind_target(i);
  35. _s->reset(actual_sp_base() + uw->offset); // unwind the stack
  36. _s->push(obj); // push it back
  37. return c11__at(CodeBlock, &co->blocks, i)->end;
  38. }
  39. int Frame::_exit_block(ValueStack* _s, int i) {
  40. CodeBlock* block = c11__at(CodeBlock, &co->blocks, i);
  41. if(block->type == CodeBlockType_FOR_LOOP) {
  42. _s->pop(); // pop the iterator
  43. } else if(block->type == CodeBlockType_CONTEXT_MANAGER) {
  44. _s->pop();
  45. }
  46. return block->parent;
  47. }
  48. void Frame::prepare_jump_break(ValueStack* _s, int target) {
  49. int i = c11__at(BytecodeEx, &co->codes_ex, ip())->iblock;
  50. if(target >= co->codes.count) {
  51. while(i >= 0) i = _exit_block(_s, i);
  52. } else {
  53. // BUG (solved)
  54. // for i in range(4):
  55. // _ = 0
  56. // # if there is no op here, the block check will fail
  57. // while i: --i
  58. int next_block = c11__at(BytecodeEx, &co->codes_ex, target)->iblock;
  59. while(i >= 0 && i != next_block)
  60. i = _exit_block(_s, i);
  61. assert(i == next_block);
  62. }
  63. }
  64. void Frame::set_unwind_target(PyVar* _sp) {
  65. int iblock = c11__at(BytecodeEx, &co->codes_ex, ip())->iblock;
  66. UnwindTarget* existing = find_unwind_target(iblock);
  67. if(existing) {
  68. existing->offset = _sp - actual_sp_base();
  69. } else {
  70. UnwindTarget* prev = _uw_list;
  71. _uw_list = new UnwindTarget(iblock, _sp - actual_sp_base());
  72. _uw_list->next = prev;
  73. }
  74. }
  75. UnwindTarget* Frame::find_unwind_target(int iblock) {
  76. UnwindTarget* p;
  77. for(p = _uw_list; p != nullptr; p = p->next) {
  78. if(p->iblock == iblock) return p;
  79. }
  80. return nullptr;
  81. }
  82. Frame::~Frame() {
  83. while(_uw_list != nullptr) {
  84. UnwindTarget* p = _uw_list;
  85. _uw_list = p->next;
  86. delete p;
  87. }
  88. }
  89. void CallStack::pop() {
  90. assert(!empty());
  91. LinkedFrame* p = _tail;
  92. _tail = p->f_back;
  93. p->~LinkedFrame();
  94. PoolFrame_dealloc(p);
  95. --_size;
  96. }
  97. LinkedFrame* CallStack::popx() {
  98. assert(!empty());
  99. LinkedFrame* p = _tail;
  100. _tail = p->f_back;
  101. --_size;
  102. p->f_back = nullptr; // unlink
  103. return p;
  104. }
  105. void CallStack::pushx(LinkedFrame* p) {
  106. p->f_back = _tail;
  107. _tail = p;
  108. ++_size;
  109. }
  110. } // namespace pkpy