blueloveTH hai 1 ano
pai
achega
96ff66ef69

+ 1 - 2
include/pocketpy/interpreter/vm.h

@@ -136,5 +136,4 @@ py_Type pk_code__register();
 py_TValue pk_builtins__register();
 
 /* mappingproxy */
-void pk_mappingproxy__namedict(py_Ref out, py_Ref object);
-void pk_mappingproxy__locals(py_Ref out, Frame* frame);
+void pk_mappingproxy__namedict(py_Ref out, py_Ref object);

+ 35 - 71
src/interpreter/ceval.c

@@ -208,38 +208,31 @@ FrameResult VM__run_top_frame(VM* self) {
                 DISPATCH();
             }
             case OP_LOAD_NAME: {
-                // assert(frame->is_dynamic);
                 py_Name name = byte.arg;
-                py_TValue* tmp;
-                py_assign(SP()++, py_name2ref(name));
                 // locals
-                if(!py_isnone(&frame->p0[1])) {
-                    if(py_getitem(&frame->p0[1], TOP())) {
-                        py_assign(TOP(), py_retval());
-                        DISPATCH();
-                    } else {
-                        if(py_matchexc(tp_KeyError)) {
-                            py_clearexc(NULL);
-                        } else {
-                            goto __ERROR;
-                        }
-                    }
+                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();
                 }
                 // globals
-                if(py_getitem(&frame->p0[0], TOP())) {
-                    py_assign(TOP(), py_retval());
+                res = Frame__getglobal(frame, name);
+                if(res == 1) {
+                    PUSH(&self->last_retval);
                     DISPATCH();
-                } else {
-                    if(py_matchexc(tp_KeyError)) {
-                        py_clearexc(NULL);
-                    } else {
-                        goto __ERROR;
-                    }
                 }
+                if(res == -1) goto __ERROR;
                 // builtins
                 tmp = py_getdict(&self->builtins, name);
                 if(tmp != NULL) {
-                    py_assign(TOP(), tmp);
+                    PUSH(tmp);
                     DISPATCH();
                 }
                 NameError(name);
@@ -353,36 +346,22 @@ FrameResult VM__run_top_frame(VM* self) {
                 DISPATCH();
             }
             case OP_STORE_NAME: {
-                // assert(frame->is_dynamic);
                 py_Name name = byte.arg;
-                py_assign(SP()++, py_name2ref(name));
-                // [value, name]
-                if(!py_isnone(&frame->p0[1])) {
+                if(frame->locals != NULL) {
                     // locals
-                    if(py_setitem(&frame->p0[1], TOP(), SECOND())) {
-                        STACK_SHRINK(2);
+                    int res = Frame__setlocal(frame, name, TOP());
+                    if(res == 1) {
+                        POP();
                         DISPATCH();
-                    } else {
-                        if(py_matchexc(tp_KeyError)) {
-                            py_clearexc(NULL);
-                            NameError(name);
-                        }
-                        goto __ERROR;
                     }
+                    if(res == 0) NameError(name);
+                    goto __ERROR;
                 } else {
                     // globals
-                    if(py_setitem(&frame->p0[0], TOP(), SECOND())) {
-                        STACK_SHRINK(2);
-                        DISPATCH();
-                    } else {
-                        if(py_matchexc(tp_KeyError)) {
-                            py_clearexc(NULL);
-                            NameError(name);
-                        }
-                        goto __ERROR;
-                    }
+                    if(!Frame__setglobal(frame, name, TOP())) { goto __ERROR; }
+                    POP();
+                    DISPATCH();
                 }
-                DISPATCH();
             }
             case OP_STORE_GLOBAL: {
                 if(!Frame__setglobal(frame, byte.arg, TOP())) goto __ERROR;
@@ -424,42 +403,27 @@ FrameResult VM__run_top_frame(VM* self) {
                 DISPATCH();
             }
             case OP_DELETE_NAME: {
-                // assert(frame->is_dynamic);
                 py_Name name = byte.arg;
-                py_assign(SP()++, py_name2ref(name));
-                if(!py_isnone(&frame->p0[1])) {
+                if(frame->locals != NULL) {
                     // locals
-                    if(py_delitem(&frame->p0[1], TOP())) {
-                        POP();
-                        DISPATCH();
-                    } else {
-                        if(py_matchexc(tp_KeyError)) {
-                            py_clearexc(NULL);
-                            NameError(name);
-                        }
-                        goto __ERROR;
-                    }
+                    int res = Frame__dellocal(frame, name);
+                    if(res == 1) DISPATCH();
+                    if(res == 0) NameError(name);
+                    goto __ERROR;
                 } else {
                     // globals
-                    if(py_delitem(&frame->p0[0], TOP())) {
-                        POP();
-                        DISPATCH();
-                    } else {
-                        if(py_matchexc(tp_KeyError)) {
-                            py_clearexc(NULL);
-                            NameError(name);
-                        }
-                        goto __ERROR;
-                    }
+                    int res = Frame__delglobal(frame, name);
+                    if(res == 1) DISPATCH();
+                    if(res == 0) NameError(name);
+                    goto __ERROR;
+                    DISPATCH();
                 }
-                DISPATCH();
             }
             case OP_DELETE_GLOBAL: {
                 py_Name name = byte.arg;
                 int res = Frame__delglobal(frame, name);
                 if(res == 1) DISPATCH();
                 if(res == -1) goto __ERROR;
-                // res == 0
                 NameError(name);
                 goto __ERROR;
             }

+ 5 - 5
src/interpreter/frame.c

@@ -54,7 +54,9 @@ Frame* Frame__new(const CodeObject* co,
                   py_Ref locals,
                   bool is_p0_function,
                   bool is_locals_proxy) {
-    assert(module->type == tp_module || module->type == tp_dict);
+    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);
     Frame* self = FixedMemoryPool__alloc(&pk_current_vm->pool_frame);
     self->f_back = NULL;
     self->co = co;
@@ -78,10 +80,8 @@ void Frame__delete(Frame* self) {
     FixedMemoryPool__dealloc(&pk_current_vm->pool_frame, self);
 }
 
-py_StackRef Frame__locals_sp(Frame *self){
-    if(!self->is_locals_proxy){
-        return self->locals;
-    }
+py_StackRef Frame__locals_sp(Frame* self) {
+    if(!self->is_locals_proxy) { return self->locals; }
     return self->p0;
 }
 

+ 3 - 5
src/public/exec.c

@@ -3,15 +3,13 @@
 #include "pocketpy/pocketpy.h"
 
 #include "pocketpy/common/utils.h"
-#include "pocketpy/common/sstream.h"
-#include "pocketpy/objects/object.h"
 #include "pocketpy/interpreter/vm.h"
 #include "pocketpy/compiler/compiler.h"
 #include <assert.h>
 
 py_Type pk_code__register() {
     py_Type type = pk_newtype("code", tp_object, NULL, (py_Dtor)CodeObject__dtor, false, true);
-    pk__tp_set_marker(type, (void (*)(void *))CodeObject__gc_mark);
+    pk__tp_set_marker(type, (void (*)(void*))CodeObject__gc_mark);
     return type;
 }
 
@@ -56,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, sp, false, false);
+    Frame* frame = Frame__new(co, sp, module, module, py_NIL(), false, false);
     VM__push_frame(vm, frame);
     FrameResult res = VM__run_top_frame(vm);
     if(res == RES_ERROR) return false;
@@ -70,7 +68,7 @@ bool pk_execdyn(CodeObject* co, py_Ref module, py_Ref globals, py_Ref locals) {
     assert(module->type == tp_module);
 
     py_StackRef sp = vm->stack.sp;
-    assert(globals != NULL && locals != NULL);
+    assert(globals != NULL);
 
     if(globals->type == tp_namedict) {
         globals = py_getslot(globals, 0);

+ 53 - 17
src/public/modules.c

@@ -507,7 +507,7 @@ void py_newglobals(py_Ref out) {
 
 void py_newlocals(py_Ref out) {
     Frame* frame = pk_current_vm->top_frame;
-    if(!frame || !frame->is_p0_function) {
+    if(!frame) {
         py_newglobals(out);
         return;
     }
@@ -524,61 +524,97 @@ void py_newlocals(py_Ref out) {
     py_assign(out, py_retval());
 }
 
+static void pk_push_locals_proxy() {
+    Frame* frame = pk_current_vm->top_frame;
+    if(!frame) {
+        py_pushnil();
+        return;
+    }
+    if(frame->is_locals_proxy) {
+        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;
+        }
+    }
+}
+
 static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_CompileMode mode) {
     switch(argc) {
         case 1: {
             py_newglobals(py_pushtmp());
-            py_newlocals(py_pushtmp());
+            pk_push_locals_proxy();
             break;
         }
         case 2: {
+            // globals
             if(py_isnone(py_arg(1))) {
                 py_newglobals(py_pushtmp());
             } else {
                 if(!py_checktype(py_arg(1), tp_dict)) return false;
                 py_push(py_arg(1));
             }
-            py_pushnone();
+            // locals
+            pk_push_locals_proxy();
             break;
         }
         case 3: {
+            // globals
             if(py_isnone(py_arg(1))) {
                 py_newglobals(py_pushtmp());
             } else {
                 if(!py_checktype(py_arg(1), tp_dict)) return false;
                 py_push(py_arg(1));
             }
-            py_push(py_arg(2));
+            // locals
+            if(py_isnone(py_arg(2))) {
+                pk_push_locals_proxy();
+            } else {
+                if(!py_checktype(py_arg(2), tp_dict)) return false;
+                py_push(py_arg(2));
+            }
             break;
         }
         default: return TypeError("%s() takes at most 3 arguments", title);
     }
 
-    py_Ref code;
+    py_Ref tmp_code;
     if(py_isstr(argv)) {
         bool ok = py_compile(py_tostr(argv), "<string>", mode, true);
         if(!ok) return false;
-        code = py_retval();
+        tmp_code = py_retval();
     } else if(py_istype(argv, tp_code)) {
-        code = argv;
+        tmp_code = argv;
     } else {
         return TypeError("%s() expected 'str' or 'code', got '%t'", title, argv->type);
     }
 
-    py_push(code);  // keep it alive
+    py_push(tmp_code);  // keep it alive
+    Frame* frame = pk_current_vm->top_frame;
 
     // [globals, locals, code]
-    CodeObject* co = py_touserdata(code);
-    if(!co->src->is_dynamic) {
+    CodeObject* code = py_touserdata(tmp_code);
+    if(code->src->is_dynamic) {
+        bool ok = pk_execdyn(code, frame ? frame->module : NULL, py_peek(-3), py_peek(-2));
         py_shrink(3);
-        if(argc != 1)
-            return ValueError("code object is not dynamic, `globals` and `locals` must be None");
+        return ok;
+    } else {
+        if(argc != 1) {
+            return ValueError(
+                "code object is not dynamic, `globals` and `locals` must not be specified");
+        }
+        bool ok = pk_exec(code, frame ? frame->module : NULL);
+        py_shrink(3);
+        return ok;
     }
-
-    Frame* frame = pk_current_vm->top_frame;
-    bool ok = pk_execdyn(co, frame ? frame->module : NULL, py_peek(-3), py_peek(-2));
-    py_shrink(3);
-    return ok;
 }
 
 static bool builtins_exec(int argc, py_Ref argv) {

+ 0 - 14
src/public/py_mappingproxy.c

@@ -1,9 +1,7 @@
 #include "pocketpy/pocketpy.h"
 
-#include "pocketpy/common/utils.h"
 #include "pocketpy/objects/object.h"
 #include "pocketpy/interpreter/vm.h"
-#include "pocketpy/common/sstream.h"
 #include <stdbool.h>
 
 void pk_mappingproxy__namedict(py_Ref out, py_Ref object) {
@@ -104,15 +102,3 @@ py_Type pk_namedict__register() {
     py_bindmethod(type, "clear", namedict_clear);
     return type;
 }
-
-//////////////////////
-
-void pk_mappingproxy__locals(py_Ref out, Frame* frame) {
-    assert(frame->is_p0_function && !frame->is_locals_proxy);
-    out->type = tp_locals;
-    out->is_ptr = false;
-    out->extra = 0;
-    // this is a weak reference
-    // locals() will expire when the frame is destroyed
-    out->_ptr = frame;
-}