1
0

frame.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include "pocketpy/interpreter/frame.h"
  2. #include "pocketpy/objects/object.h"
  3. void ValueStack__ctor(ValueStack* self) {
  4. self->sp = self->begin;
  5. self->end = self->begin + PK_VM_STACK_SIZE;
  6. }
  7. void ValueStack__clear(ValueStack* self) {
  8. self->sp = self->begin;
  9. }
  10. py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co, py_Name name){
  11. int index = c11_smallmap_n2i__get(&co->varnames_inv, name, -1);
  12. if(index == -1) return NULL;
  13. return &locals[index];
  14. }
  15. pk_NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
  16. pk_NameDict* dict = pk_NameDict__new();
  17. c11__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) {
  18. py_TValue value = locals[entry->value];
  19. if(!py_isnull(&value)){
  20. pk_NameDict__set(dict, entry->key, value);
  21. }
  22. }
  23. return dict;
  24. }
  25. UnwindTarget* UnwindTarget__new(UnwindTarget* next, int iblock, int offset){
  26. UnwindTarget* self = malloc(sizeof(UnwindTarget));
  27. self->next = next;
  28. self->iblock = iblock;
  29. self->offset = offset;
  30. return self;
  31. }
  32. void UnwindTarget__delete(UnwindTarget* self){
  33. free(self);
  34. }
  35. Frame* Frame__new(const CodeObject* co, const py_TValue* module, const py_TValue* function, py_TValue* p0, py_TValue* locals, const CodeObject* locals_co){
  36. static_assert(sizeof(Frame) <= kPoolFrameBlockSize, "!(sizeof(Frame) <= kPoolFrameBlockSize)");
  37. Frame* self = PoolFrame_alloc();
  38. self->f_back = NULL;
  39. self->ip = (Bytecode*)co->codes.data - 1;
  40. self->co = co;
  41. self->module = module->_obj;
  42. self->function = function ? function->_obj : NULL;
  43. self->p0 = p0;
  44. self->locals = locals;
  45. self->locals_co = locals_co;
  46. self->uw_list = NULL;
  47. return self;
  48. }
  49. void Frame__delete(Frame* self){
  50. while(self->uw_list) {
  51. UnwindTarget* p = self->uw_list;
  52. self->uw_list = p->next;
  53. UnwindTarget__delete(p);
  54. }
  55. PoolFrame_dealloc(self);
  56. }
  57. int Frame__prepare_jump_exception_handler(Frame* self, ValueStack* _s){
  58. // try to find a parent try block
  59. int iblock = Frame__iblock(self);
  60. while(iblock >= 0) {
  61. CodeBlock* block = c11__at(CodeBlock, &self->co->blocks, iblock);
  62. if(block->type == CodeBlockType_TRY_EXCEPT) break;
  63. iblock = block->parent;
  64. }
  65. if(iblock < 0) return -1;
  66. py_TValue obj = *--_s->sp; // pop exception object
  67. UnwindTarget* uw = Frame__find_unwind_target(self, iblock);
  68. _s->sp = (self->locals + uw->offset); // unwind the stack
  69. *(_s->sp++) = obj; // push it back
  70. return c11__at(CodeBlock, &self->co->blocks, iblock)->end;
  71. }
  72. void Frame__prepare_jump_break(Frame* self, ValueStack* _s, int target){
  73. int iblock = Frame__iblock(self);
  74. if(target >= self->co->codes.count) {
  75. while(iblock >= 0) iblock = Frame__exit_block(self, _s, iblock);
  76. } else {
  77. // BUG (solved)
  78. // for i in range(4):
  79. // _ = 0
  80. // # if there is no op here, the block check will fail
  81. // while i: --i
  82. int next_block = c11__at(BytecodeEx, &self->co->codes_ex, target)->iblock;
  83. while(iblock >= 0 && iblock != next_block)
  84. iblock = Frame__exit_block(self, _s, iblock);
  85. assert(iblock == next_block);
  86. }
  87. }
  88. int Frame__prepare_loop_break(Frame* self, ValueStack* _s){
  89. int iblock = Frame__iblock(self);
  90. int target = c11__getitem(CodeBlock, &self->co->blocks, iblock).end;
  91. Frame__prepare_jump_break(self, _s, target);
  92. return target;
  93. }
  94. int Frame__exit_block(Frame* self, ValueStack* _s, int iblock){
  95. CodeBlock* block = c11__at(CodeBlock, &self->co->blocks, iblock);
  96. if(block->type == CodeBlockType_FOR_LOOP) {
  97. _s->sp--; // pop iterator
  98. } else if(block->type == CodeBlockType_CONTEXT_MANAGER) {
  99. _s->sp--; // pop context variable
  100. }
  101. return block->parent;
  102. }
  103. UnwindTarget* Frame__find_unwind_target(Frame* self, int iblock){
  104. UnwindTarget* uw;
  105. for(uw = self->uw_list; uw; uw = uw->next) {
  106. if(uw->iblock == iblock) return uw;
  107. }
  108. return NULL;
  109. }
  110. void Frame__set_unwind_target(Frame* self, py_TValue* sp) {
  111. int iblock = Frame__iblock(self);
  112. UnwindTarget* existing = Frame__find_unwind_target(self, iblock);
  113. if(existing) {
  114. existing->offset = sp - self->locals;
  115. } else {
  116. UnwindTarget* prev = self->uw_list;
  117. self->uw_list = UnwindTarget__new(prev, iblock, sp - self->locals);
  118. }
  119. }
  120. py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name){
  121. // if(self->function == NULL) return NULL;
  122. // pkpy::Function* fn = PyObject__as(pkpy::Function, self->function);
  123. // if(fn->_closure == nullptr) return nullptr;
  124. // return pk_NameDict__try_get(fn->_closure, name);
  125. return NULL;
  126. }