frame.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  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 == 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 (depth of for loops)
  32. int _stack_size = co->blocks[block].for_loop_depth;
  33. if(stack_size() < _stack_size) throw std::runtime_error("invalid stack size");
  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. if(co->blocks[i].type == FOR_LOOP) _s->pop();
  41. return co->blocks[i].parent;
  42. }
  43. void Frame::jump_abs_break(int target){
  44. int i = co->iblocks[_ip];
  45. _next_ip = target;
  46. if(_next_ip >= co->codes.size()){
  47. while(i>=0) i = _exit_block(i);
  48. }else{
  49. // BUG (solved)
  50. // for i in range(4):
  51. // _ = 0
  52. // # if there is no op here, the block check will fail
  53. // while i: --i
  54. int next_block = co->iblocks[target];
  55. while(i>=0 && i!=next_block) i = _exit_block(i);
  56. if(i!=next_block) throw std::runtime_error("invalid jump");
  57. }
  58. }
  59. } // namespace pkpy