frame.cpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. #include "pocketpy/frame.h"
  2. namespace pkpy{
  3. PyVar* FastLocals::try_get_name(StrName name){
  4. int index = co->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. co->varnames_inv.apply([&](StrName name, int index){
  11. PyVar value = a[index];
  12. if(value != PY_NULL) dict->set(name, value);
  13. });
  14. return dict;
  15. }
  16. PyVar 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. int Frame::prepare_jump_exception_handler(ValueStack* _s){
  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 -1;
  30. PyVar 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(_s) < _stack_size) throw std::runtime_error(_S("invalid state: ", stack_size(_s), '<', _stack_size).str());
  34. _s->reset(actual_sp_base() + _locals.size() + _stack_size); // rollback the stack
  35. _s->push(obj); // push exception object
  36. return co->blocks[block].end;
  37. }
  38. int Frame::_exit_block(ValueStack* _s, int i){
  39. auto type = co->blocks[i].type;
  40. if(type==CodeBlockType::FOR_LOOP || type==CodeBlockType::CONTEXT_MANAGER) _s->pop();
  41. return co->blocks[i].parent;
  42. }
  43. void Frame::prepare_jump_break(ValueStack* _s, int target){
  44. int i = co->iblocks[ip()];
  45. if(target >= co->codes.size()){
  46. while(i>=0) i = _exit_block(_s, i);
  47. }else{
  48. // BUG (solved)
  49. // for i in range(4):
  50. // _ = 0
  51. // # if there is no op here, the block check will fail
  52. // while i: --i
  53. int next_block = co->iblocks[target];
  54. while(i>=0 && i!=next_block) i = _exit_block(_s, i);
  55. if(i!=next_block) throw std::runtime_error("invalid jump");
  56. }
  57. }
  58. } // namespace pkpy