blueloveTH 1 рік тому
батько
коміт
bf7bfa938c

+ 0 - 4
include/pocketpy/interpreter/frame.h

@@ -55,10 +55,6 @@ int Frame__getglobal(Frame* self, py_Name name) PY_RAISE PY_RETURN;
 bool Frame__setglobal(Frame* self, py_Name name, py_TValue* val) PY_RAISE;
 int Frame__delglobal(Frame* self, py_Name name) PY_RAISE;
 
-int Frame__getlocal(Frame* self, py_Name name) PY_RAISE PY_RETURN;
-bool Frame__setlocal(Frame* self, py_Name name, py_TValue* val) PY_RAISE;
-int Frame__dellocal(Frame* self, py_Name name) PY_RAISE;
-
 py_Ref Frame__getclosure(Frame* self, py_Name name);
 py_StackRef Frame__getlocal_noproxy(Frame* self, py_Name name);
 

+ 74 - 37
src/interpreter/ceval.c

@@ -208,29 +208,43 @@ FrameResult VM__run_top_frame(VM* self) {
                 DISPATCH();
             }
             case OP_LOAD_NAME: {
+                assert(frame->is_locals_special);
                 py_Name name = byte.arg;
                 // locals
-                int res = Frame__getlocal(frame, name);
-                if(res == 1) {
-                    PUSH(&self->last_retval);
-                    DISPATCH();
-                }
-                if(res == -1) goto __ERROR;
-                // closure
-                py_Ref tmp = Frame__getclosure(frame, name);
-                if(tmp != NULL) {
-                    PUSH(tmp);
-                    DISPATCH();
+                switch(frame->locals->type) {
+                    case tp_locals: {
+                        Frame* noproxy = frame->locals->_ptr;
+                        py_Ref slot = Frame__getlocal_noproxy(noproxy, name);
+                        if(slot == NULL) break;
+                        if(py_isnil(slot)) {
+                            UnboundLocalError(name);
+                            goto __ERROR;
+                        }
+                        PUSH(slot);
+                        DISPATCH();
+                    }
+                    case tp_dict: {
+                        int res = py_dict_getitem(frame->locals, py_name2ref(name));
+                        if(res == 1) {
+                            PUSH(&self->last_retval);
+                            DISPATCH();
+                        }
+                        if(res == 0) break;
+                        assert(res == -1);
+                        goto __ERROR;
+                    }
+                    case tp_nil: break;
+                    default: c11__unreachable();
                 }
                 // globals
-                res = Frame__getglobal(frame, name);
+                int res = Frame__getglobal(frame, name);
                 if(res == 1) {
                     PUSH(&self->last_retval);
                     DISPATCH();
                 }
                 if(res == -1) goto __ERROR;
                 // builtins
-                tmp = py_getdict(&self->builtins, name);
+                py_Ref tmp = py_getdict(&self->builtins, name);
                 if(tmp != NULL) {
                     PUSH(tmp);
                     DISPATCH();
@@ -346,21 +360,31 @@ FrameResult VM__run_top_frame(VM* self) {
                 DISPATCH();
             }
             case OP_STORE_NAME: {
+                assert(frame->is_locals_special);
                 py_Name name = byte.arg;
-                if(frame->locals != NULL) {
-                    // locals
-                    int res = Frame__setlocal(frame, name, TOP());
-                    if(res == 1) {
+                switch(frame->locals->type) {
+                    case tp_locals: {
+                        Frame* noproxy = frame->locals->_ptr;
+                        py_Ref slot = Frame__getlocal_noproxy(noproxy, name);
+                        if(slot == NULL) {
+                            UnboundLocalError(name);
+                            goto __ERROR;
+                        }
+                        *slot = POPX();
+                        DISPATCH();
+                    }
+                    case tp_dict: {
+                        if(!py_dict_setitem(frame->locals, py_name2ref(name), TOP())) goto __ERROR;
                         POP();
                         DISPATCH();
                     }
-                    if(res == 0) NameError(name);
-                    goto __ERROR;
-                } else {
-                    // globals
-                    if(!Frame__setglobal(frame, name, TOP())) { goto __ERROR; }
-                    POP();
-                    DISPATCH();
+                    case tp_nil: {
+                        // globals
+                        if(!Frame__setglobal(frame, name, TOP())) goto __ERROR;
+                        POP();
+                        DISPATCH();
+                    }
+                    default: c11__unreachable();
                 }
             }
             case OP_STORE_GLOBAL: {
@@ -403,20 +427,33 @@ FrameResult VM__run_top_frame(VM* self) {
                 DISPATCH();
             }
             case OP_DELETE_NAME: {
+                assert(frame->is_locals_special);
                 py_Name name = byte.arg;
-                if(frame->locals != NULL) {
-                    // locals
-                    int res = Frame__dellocal(frame, name);
-                    if(res == 1) DISPATCH();
-                    if(res == 0) NameError(name);
-                    goto __ERROR;
-                } else {
-                    // globals
-                    int res = Frame__delglobal(frame, name);
-                    if(res == 1) DISPATCH();
-                    if(res == 0) NameError(name);
-                    goto __ERROR;
-                    DISPATCH();
+                switch(frame->locals->type) {
+                    case tp_locals: {
+                        Frame* noproxy = frame->locals->_ptr;
+                        py_Ref slot = Frame__getlocal_noproxy(noproxy, name);
+                        if(slot == NULL || py_isnil(slot)) {
+                            UnboundLocalError(name);
+                            goto __ERROR;
+                        }
+                        py_newnil(slot);
+                        DISPATCH();
+                    }
+                    case tp_dict: {
+                        int res = py_dict_delitem(frame->locals, py_name2ref(name));
+                        if(res == 1) DISPATCH();
+                        if(res == 0) UnboundLocalError(name);
+                        goto __ERROR;
+                    }
+                    case tp_nil: {
+                        // globals
+                        int res = Frame__delglobal(frame, name);
+                        if(res == 1) DISPATCH();
+                        if(res == 0) NameError(name);
+                        goto __ERROR;
+                    }
+                    default: c11__unreachable();
                 }
             }
             case OP_DELETE_GLOBAL: {

+ 0 - 53
src/interpreter/frame.c

@@ -160,59 +160,6 @@ int Frame__delglobal(Frame* self, py_Name name) {
     }
 }
 
-int Frame__getlocal(Frame* self, py_Name 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);
-    if(slot == NULL) return 0;  // bad slot
-    if(py_isnil(slot)) {
-        UnboundLocalError(name);
-        return -1;
-    }
-    py_assign(py_retval(), slot);
-    return 1;
-}
-
-bool Frame__setlocal(Frame* self, py_Name name, py_TValue* 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);
-    if(slot == NULL) return false;  // bad slot
-    *slot = *val;
-    return true;
-}
-
-int Frame__dellocal(Frame* self, py_Name 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);
-    if(slot == NULL) return 0;  // bad slot
-    if(py_isnil(slot)) {
-        UnboundLocalError(name);
-        return -1;
-    }
-    py_newnil(slot);
-    return 1;
-}
-
 py_StackRef Frame__getlocal_noproxy(Frame* self, py_Name name) {
     assert(!self->is_locals_special);
     int index = c11_smallmap_n2i__get(&self->co->varnames_inv, name, -1);

+ 7 - 10
src/public/modules.c

@@ -523,7 +523,7 @@ void py_newlocals(py_Ref out) {
     py_assign(out, py_retval());
 }
 
-static void pk_push_locals_proxy() {
+static void pk_push_special_locals() {
     Frame* frame = pk_current_vm->top_frame;
     if(!frame) {
         py_pushnil();
@@ -546,7 +546,7 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_
     switch(argc) {
         case 1: {
             py_newglobals(py_pushtmp());
-            pk_push_locals_proxy();
+            pk_push_special_locals();
             break;
         }
         case 2: {
@@ -558,7 +558,7 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_
                 py_push(py_arg(1));
             }
             // locals
-            pk_push_locals_proxy();
+            pk_push_special_locals();
             break;
         }
         case 3: {
@@ -571,7 +571,7 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_
             }
             // locals
             if(py_isnone(py_arg(2))) {
-                pk_push_locals_proxy();
+                pk_push_special_locals();
             } else {
                 if(!py_checktype(py_arg(2), tp_dict)) return false;
                 py_push(py_arg(2));
@@ -581,22 +581,19 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_
         default: return TypeError("%s() takes at most 3 arguments", title);
     }
 
-    py_Ref tmp_code;
     if(py_isstr(argv)) {
         bool ok = py_compile(py_tostr(argv), "<string>", mode, true);
         if(!ok) return false;
-        tmp_code = py_retval();
+        py_push(py_retval());
     } else if(py_istype(argv, tp_code)) {
-        tmp_code = argv;
+        py_push(argv);
     } else {
         return TypeError("%s() expected 'str' or 'code', got '%t'", title, argv->type);
     }
 
-    py_push(tmp_code);  // keep it alive
     Frame* frame = pk_current_vm->top_frame;
-
     // [globals, locals, code]
-    CodeObject* code = py_touserdata(tmp_code);
+    CodeObject* code = py_touserdata(py_peek(-1));
     if(code->src->is_dynamic) {
         bool ok = pk_execdyn(code, frame ? frame->module : NULL, py_peek(-3), py_peek(-2));
         py_shrink(3);