blueloveTH 1 rok temu
rodzic
commit
330e005881

+ 3 - 5
include/pocketpy/interpreter/frame.h

@@ -34,9 +34,8 @@ typedef struct Frame {
     py_StackRef p0;  // unwinding base
     py_GlobalRef module;
     py_Ref globals;  // a module object or a dict object
-    py_Ref locals;   // locals base or a proxy object (such as dict)
-    bool is_p0_function;
-    bool is_locals_proxy;
+    py_Ref locals;
+    bool is_locals_special;
     int ip;
     UnwindTarget* uw_list;
 } Frame;
@@ -46,8 +45,7 @@ Frame* Frame__new(const CodeObject* co,
                   py_GlobalRef module,
                   py_Ref globals,
                   py_Ref locals,
-                  bool is_p0_function,
-                  bool is_locals_proxy);
+                  bool is_locals_special);
 void Frame__delete(Frame* self);
 
 int Frame__lineno(const Frame* self);

+ 6 - 6
src/interpreter/ceval.c

@@ -181,8 +181,8 @@ FrameResult VM__run_top_frame(VM* self) {
                 Function* ud = py_newobject(SP(), tp_function, 0, sizeof(Function));
                 Function__ctor(ud, decl, frame->module, frame->globals);
                 if(decl->nested) {
-                    if(frame->is_locals_proxy) {
-                        RuntimeError("cannot create closure from locals proxy");
+                    if(frame->is_locals_special) {
+                        RuntimeError("cannot create closure from special locals");
                         goto __ERROR;
                     }
                     ud->closure = FastLocals__to_namedict(frame->locals, frame->co);
@@ -198,7 +198,7 @@ FrameResult VM__run_top_frame(VM* self) {
                 DISPATCH();
                 /*****************************************/
             case OP_LOAD_FAST: {
-                assert(!frame->is_locals_proxy);
+                assert(!frame->is_locals_special);
                 PUSH(&frame->locals[byte.arg]);
                 if(py_isnil(TOP())) {
                     py_Name name = c11__getitem(uint16_t, &frame->co->varnames, byte.arg);
@@ -341,7 +341,7 @@ FrameResult VM__run_top_frame(VM* self) {
                 goto __ERROR;
             }
             case OP_STORE_FAST: {
-                assert(!frame->is_locals_proxy);
+                assert(!frame->is_locals_special);
                 frame->locals[byte.arg] = POPX();
                 DISPATCH();
             }
@@ -392,7 +392,7 @@ FrameResult VM__run_top_frame(VM* self) {
                 goto __ERROR;
             }
             case OP_DELETE_FAST: {
-                assert(!frame->is_locals_proxy);
+                assert(!frame->is_locals_special);
                 py_Ref tmp = &frame->locals[byte.arg];
                 if(py_isnil(tmp)) {
                     py_Name name = c11__getitem(py_Name, &frame->co->varnames, byte.arg);
@@ -1146,7 +1146,7 @@ FrameResult VM__run_top_frame(VM* self) {
         py_BaseException__stpush(&self->curr_exception,
                                  frame->co->src,
                                  Frame__lineno(frame),
-                                 frame->is_p0_function ? frame->co->name->data : NULL);
+                                 !frame->is_locals_special ? frame->co->name->data : NULL);
     __ERROR_RE_RAISE:
         do {
         } while(0);

+ 28 - 28
src/interpreter/frame.c

@@ -52,11 +52,12 @@ Frame* Frame__new(const CodeObject* co,
                   py_GlobalRef module,
                   py_Ref globals,
                   py_Ref locals,
-                  bool is_p0_function,
-                  bool is_locals_proxy) {
+                  bool is_locals_special) {
     assert(module->type == tp_module);
     assert(globals->type == tp_module || globals->type == tp_dict);
-    assert(locals->type == tp_locals || locals->type == tp_dict || locals->type == tp_nil);
+    if(is_locals_special) {
+        assert(locals->type == tp_nil || locals->type == tp_locals || locals->type == tp_dict);
+    }
     Frame* self = FixedMemoryPool__alloc(&pk_current_vm->pool_frame);
     self->f_back = NULL;
     self->co = co;
@@ -64,8 +65,7 @@ Frame* Frame__new(const CodeObject* co,
     self->module = module;
     self->globals = globals;
     self->locals = locals;
-    self->is_p0_function = is_p0_function;
-    self->is_locals_proxy = is_locals_proxy;
+    self->is_locals_special = is_locals_special;
     self->ip = -1;
     self->uw_list = NULL;
     return self;
@@ -81,8 +81,7 @@ void Frame__delete(Frame* self) {
 }
 
 py_StackRef Frame__locals_sp(Frame* self) {
-    if(!self->is_locals_proxy) { return self->locals; }
-    return self->p0;
+    return !self->is_locals_special ? self->locals : self->p0;
 }
 
 int Frame__prepare_jump_exception_handler(Frame* self, ValueStack* _s) {
@@ -120,7 +119,7 @@ void Frame__set_unwind_target(Frame* self, py_TValue* sp) {
 
 void Frame__gc_mark(Frame* self) {
     pk__mark_value(self->globals);
-    if(self->is_locals_proxy) pk__mark_value(self->locals);
+    if(self->is_locals_special) pk__mark_value(self->locals);
     CodeObject__gc_mark(self->co);
 }
 
@@ -166,12 +165,12 @@ int Frame__delglobal(Frame* self, py_Name name) {
 }
 
 int Frame__getlocal(Frame* self, py_Name name) {
-    if(self->is_locals_proxy) {
-        if(self->locals->type == tp_locals) {
-            self = self->locals->_ptr;
-        } else {
-            assert(self->locals->type == tp_dict);
-            return py_dict_getitem(self->locals, py_name2ref(name));
+    if(self->is_locals_special) {
+        switch(self->locals->type) {
+            case tp_locals: self = self->locals->_ptr; break;
+            case tp_dict: return py_dict_getitem(self->locals, py_name2ref(name));
+            case tp_nil: return 0;
+            default: c11__unreachable();
         }
     }
     py_Ref slot = Frame__getlocal_noproxy(self, name);
@@ -185,12 +184,12 @@ int Frame__getlocal(Frame* self, py_Name name) {
 }
 
 bool Frame__setlocal(Frame* self, py_Name name, py_TValue* val) {
-    if(self->is_locals_proxy) {
-        if(self->locals->type == tp_locals) {
-            self = self->locals->_ptr;
-        } else {
-            assert(self->locals->type == tp_dict);
-            return py_dict_setitem(self->locals, py_name2ref(name), val);
+    if(self->is_locals_special) {
+        switch(self->locals->type) {
+            case tp_locals: self = self->locals->_ptr; break;
+            case tp_dict: return py_dict_setitem(self->locals, py_name2ref(name), val);
+            case tp_nil: return false;
+            default: c11__unreachable();
         }
     }
     py_Ref slot = Frame__getlocal_noproxy(self, name);
@@ -200,12 +199,12 @@ bool Frame__setlocal(Frame* self, py_Name name, py_TValue* val) {
 }
 
 int Frame__dellocal(Frame* self, py_Name name) {
-    if(self->is_locals_proxy) {
-        if(self->locals->type == tp_locals) {
-            self = self->locals->_ptr;
-        } else {
-            assert(self->locals->type == tp_dict);
-            return py_dict_delitem(self->locals, py_name2ref(name));
+    if(self->is_locals_special) {
+        switch(self->locals->type) {
+            case tp_locals: self = self->locals->_ptr; break;
+            case tp_dict: return py_dict_delitem(self->locals, py_name2ref(name));
+            case tp_nil: return 0;
+            default: c11__unreachable();
         }
     }
     py_Ref slot = Frame__getlocal_noproxy(self, name);
@@ -219,14 +218,15 @@ int Frame__dellocal(Frame* self, py_Name name) {
 }
 
 py_StackRef Frame__getlocal_noproxy(Frame* self, py_Name name) {
-    assert(!self->is_locals_proxy);
+    assert(!self->is_locals_special);
     int index = c11_smallmap_n2i__get(&self->co->varnames_inv, name, -1);
     if(index == -1) return NULL;
     return &self->locals[index];
 }
 
 py_Ref Frame__getclosure(Frame* self, py_Name name) {
-    if(!self->is_p0_function) return NULL;
+    if(self->is_locals_special) return NULL;
+    assert(self->p0->type == tp_function);
     Function* ud = py_touserdata(self->p0);
     if(ud->closure == NULL) return NULL;
     return NameDict__try_get(ud->closure, name);

+ 1 - 3
src/interpreter/generator.c

@@ -28,9 +28,7 @@ static bool generator__next__(int argc, py_Ref argv) {
     if(ud->state == 2) return StopIteration();
 
     // reset frame->p0
-    if(ud->frame->is_locals_proxy){
-        return RuntimeError("cannot resume generator with locals proxy");
-    }
+    assert(!ud->frame->is_locals_special);
     int locals_offset = ud->frame->locals - ud->frame->p0;
     ud->frame->p0 = py_peek(0);
     ud->frame->locals = ud->frame->p0 + locals_offset;

+ 3 - 5
src/interpreter/vm.c

@@ -485,8 +485,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
                 // submit the call
                 if(!fn->cfunc) {
                     // python function
-                    VM__push_frame(self,
-                                   Frame__new(co, p0, fn->module, fn->globals, argv, true, false));
+                    VM__push_frame(self, Frame__new(co, p0, fn->module, fn->globals, argv, false));
                     return opcall ? RES_CALL : VM__run_top_frame(self);
                 } else {
                     // decl-based binding
@@ -515,8 +514,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
                 // submit the call
                 if(!fn->cfunc) {
                     // python function
-                    VM__push_frame(self,
-                                   Frame__new(co, p0, fn->module, fn->globals, argv, true, false));
+                    VM__push_frame(self, Frame__new(co, p0, fn->module, fn->globals, argv, false));
                     return opcall ? RES_CALL : VM__run_top_frame(self);
                 } else {
                     // decl-based binding
@@ -532,7 +530,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
                 // copy buffer back to stack
                 self->stack.sp = argv + co->nlocals;
                 memcpy(argv, self->__vectorcall_buffer, co->nlocals * sizeof(py_TValue));
-                Frame* frame = Frame__new(co, p0, fn->module, fn->globals, argv, true, false);
+                Frame* frame = Frame__new(co, p0, fn->module, fn->globals, argv, false);
                 pk_newgenerator(py_retval(), frame, p0, self->stack.sp);
                 self->stack.sp = p0;  // reset the stack
                 return RES_RETURN;

+ 2 - 2
src/public/exec.c

@@ -54,7 +54,7 @@ bool pk_exec(CodeObject* co, py_Ref module) {
     assert(module->type == tp_module);
 
     py_StackRef sp = vm->stack.sp;
-    Frame* frame = Frame__new(co, sp, module, module, py_NIL(), false, false);
+    Frame* frame = Frame__new(co, sp, module, module, py_NIL(), true);
     VM__push_frame(vm, frame);
     FrameResult res = VM__run_top_frame(vm);
     if(res == RES_ERROR) return false;
@@ -76,7 +76,7 @@ bool pk_execdyn(CodeObject* co, py_Ref module, py_Ref globals, py_Ref locals) {
     } else {
         assert(globals->type == tp_dict);
     }
-    Frame* frame = Frame__new(co, sp, module, globals, locals, false, true);
+    Frame* frame = Frame__new(co, sp, module, globals, locals, true);
     VM__push_frame(vm, frame);
     FrameResult res = VM__run_top_frame(vm);
     if(res == RES_ERROR) return false;

+ 16 - 23
src/public/modules.c

@@ -511,13 +511,12 @@ void py_newlocals(py_Ref out) {
         py_newglobals(out);
         return;
     }
-    if(frame->is_locals_proxy) {
-        if(frame->locals->type == tp_locals) {
-            frame = frame->locals->_ptr;
-        } else {
-            assert(frame->locals->type == tp_dict);
-            *out = *frame->locals;
-            return;
+    if(frame->is_locals_special) {
+        switch(frame->locals->type) {
+            case tp_locals: frame = frame->locals->_ptr; break;
+            case tp_dict: *out = *frame->locals; return;
+            case tp_nil: py_newglobals(out); return;
+            default: c11__unreachable();
         }
     }
     FastLocals__to_dict(frame->locals, frame->co);
@@ -530,20 +529,16 @@ static void pk_push_locals_proxy() {
         py_pushnil();
         return;
     }
-    if(frame->is_locals_proxy) {
+    if(frame->is_locals_special) {
         py_push(frame->locals);
     } else {
-        if(py_isnil(frame->locals)) {
-            py_pushnil();
-        } else {
-            py_StackRef out = py_pushtmp();
-            out->type = tp_locals;
-            out->is_ptr = false;
-            out->extra = 0;
-            // this is a weak reference
-            // which will expire when the frame is destroyed
-            out->_ptr = frame;
-        }
+        py_StackRef out = py_pushtmp();
+        out->type = tp_locals;
+        out->is_ptr = false;
+        out->extra = 0;
+        // this is a weak reference
+        // which will expire when the frame is destroyed
+        out->_ptr = frame;
     }
 }
 
@@ -827,16 +822,14 @@ static bool super__new__(int argc, py_Ref argv) {
     py_Ref self_arg = NULL;
     if(argc == 1) {
         // super()
-        if(frame->is_p0_function && !frame->is_locals_proxy) {
+        if(!frame->is_locals_special) {
             py_TValue* callable = frame->p0;
             if(callable->type == tp_boundmethod) callable = py_getslot(frame->p0, 1);
             if(callable->type == tp_function) {
                 Function* func = py_touserdata(callable);
                 if(func->clazz != NULL) {
                     class_arg = *(py_Type*)PyObject__userdata(func->clazz);
-                    if(frame->co->nlocals > 0) {
-                        if(!frame->is_locals_proxy) self_arg = &frame->locals[0];
-                    }
+                    if(frame->co->nlocals > 0) { self_arg = &frame->locals[0]; }
                 }
             }
         }