frame.cpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. #include "pocketpy/frame.h"
  2. namespace pkpy{
  3. PyObject** FastLocals::try_get_name(StrName name){
  4. int index = varnames_inv->try_get(name);
  5. if(index == -1) return nullptr;
  6. return &a[index];
  7. }
  8. NameDict_ FastLocals::to_namedict(){
  9. NameDict_ dict = std::make_shared<NameDict>();
  10. varnames_inv->apply([&](StrName name, int index){
  11. PyObject* value = a[index];
  12. if(value != PY_NULL) dict->set(name, value);
  13. });
  14. return dict;
  15. }
  16. PyObject* Frame::f_closure_try_get(StrName name){
  17. if(_callable == nullptr) return nullptr;
  18. Function& fn = PK_OBJ_GET(Function, _callable);
  19. if(fn._closure == nullptr) return nullptr;
  20. return fn._closure->try_get(name);
  21. }
  22. bool Frame::jump_to_exception_handler(){
  23. // try to find a parent try block
  24. int block = co->iblocks[_ip];
  25. while(block >= 0){
  26. if(co->blocks[block].type == CodeBlockType::TRY_EXCEPT) break;
  27. block = co->blocks[block].parent;
  28. }
  29. if(block < 0) return false;
  30. PyObject* obj = _s->popx(); // pop exception object
  31. // get the stack size of the try block
  32. int _stack_size = co->blocks[block].base_stack_size;
  33. if(stack_size() < _stack_size) throw std::runtime_error(_S("invalid state: ", stack_size(), '<', _stack_size).str());
  34. _s->reset(actual_sp_base() + _locals.size() + _stack_size); // rollback the stack
  35. _s->push(obj); // push exception object
  36. _next_ip = co->blocks[block].end;
  37. return true;
  38. }
  39. int Frame::_exit_block(int i){
  40. auto type = co->blocks[i].type;
  41. if(type==CodeBlockType::FOR_LOOP || type==CodeBlockType::CONTEXT_MANAGER) _s->pop();
  42. return co->blocks[i].parent;
  43. }
  44. void Frame::jump_abs_break(int target){
  45. int i = co->iblocks[_ip];
  46. _next_ip = target;
  47. if(_next_ip >= co->codes.size()){
  48. while(i>=0) i = _exit_block(i);
  49. }else{
  50. // BUG (solved)
  51. // for i in range(4):
  52. // _ = 0
  53. // # if there is no op here, the block check will fail
  54. // while i: --i
  55. int next_block = co->iblocks[target];
  56. while(i>=0 && i!=next_block) i = _exit_block(i);
  57. if(i!=next_block) throw std::runtime_error("invalid jump");
  58. }
  59. }
  60. } // namespace pkpy