frame.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  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 = make_sp<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. Str Frame::snapshot(){
  23. int line = co->lines[_ip];
  24. return co->src->snapshot(line);
  25. }
  26. bool Frame::jump_to_exception_handler(){
  27. // try to find a parent try block
  28. int block = co->codes[_ip].block;
  29. while(block >= 0){
  30. if(co->blocks[block].type == TRY_EXCEPT) break;
  31. block = co->blocks[block].parent;
  32. }
  33. if(block < 0) return false;
  34. PyObject* obj = _s->popx(); // pop exception object
  35. // get the stack size of the try block (depth of for loops)
  36. int _stack_size = co->blocks[block].for_loop_depth;
  37. if(stack_size() < _stack_size) throw std::runtime_error("invalid stack size");
  38. _s->reset(actual_sp_base() + _locals.size() + _stack_size); // rollback the stack
  39. _s->push(obj); // push exception object
  40. _next_ip = co->blocks[block].end;
  41. return true;
  42. }
  43. int Frame::_exit_block(int i){
  44. if(co->blocks[i].type == FOR_LOOP) _s->pop();
  45. return co->blocks[i].parent;
  46. }
  47. void Frame::jump_abs_break(int target){
  48. const Bytecode& prev = co->codes[_ip];
  49. int i = prev.block;
  50. _next_ip = target;
  51. if(_next_ip >= co->codes.size()){
  52. while(i>=0) i = _exit_block(i);
  53. }else{
  54. // BUG (solved)
  55. // for i in range(4):
  56. // _ = 0
  57. // # if there is no op here, the block check will fail
  58. // while i: --i
  59. const Bytecode& next = co->codes[target];
  60. while(i>=0 && i!=next.block) i = _exit_block(i);
  61. if(i!=next.block) throw std::runtime_error("invalid jump");
  62. }
  63. }
  64. } // namespace pkpy