blueloveTH 1 год назад
Родитель
Сommit
2ba131a252

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

@@ -6,7 +6,7 @@
 #include "pocketpy/objects/object.h"
 #include "pocketpy/pocketpy.h"
 
-py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co, py_Name name);
+void FastLocals__to_dict(py_TValue* locals, const CodeObject* co) PY_RETURN;
 NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
 
 typedef struct ValueStack {
@@ -17,7 +17,7 @@ typedef struct ValueStack {
 } ValueStack;
 
 void ValueStack__ctor(ValueStack* self);
-void ValueStack__clear(ValueStack* self);
+void ValueStack__dtor(ValueStack* self);
 
 typedef struct UnwindTarget {
     struct UnwindTarget* next;
@@ -58,7 +58,7 @@ 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;
-int Frame__setlocal(Frame* self, py_Name name, py_TValue* val) PY_RAISE;
+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);

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

@@ -131,7 +131,6 @@ py_Type pk_staticmethod__register();
 py_Type pk_classmethod__register();
 py_Type pk_generator__register();
 py_Type pk_namedict__register();
-py_Type pk_locals__register();
 py_Type pk_code__register();
 
 py_TValue pk_builtins__register();

+ 0 - 1
include/pocketpy/pocketpy.h

@@ -135,7 +135,6 @@ PK_API bool py_compile(const char* source,
 /// Python equivalent to `globals()`.
 PK_API void py_newglobals(py_OutRef);
 /// Python equivalent to `locals()`.
-/// @return a temporary object, which expires on the associated function return.
 PK_API void py_newlocals(py_OutRef);
 
 /************* Values Creation *************/

+ 54 - 61
src/interpreter/frame.c

@@ -11,12 +11,21 @@ void ValueStack__ctor(ValueStack* self) {
     self->end = self->begin + PK_VM_STACK_SIZE;
 }
 
-void ValueStack__clear(ValueStack* self) { self->sp = self->begin; }
+void ValueStack__dtor(ValueStack* self) { self->sp = self->begin; }
 
-py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co, py_Name name) {
-    int index = c11_smallmap_n2i__get(&co->varnames_inv, name, -1);
-    if(index == -1) return NULL;
-    return &locals[index];
+void FastLocals__to_dict(py_TValue* locals, const CodeObject* co) {
+    py_StackRef dict = py_pushtmp();
+    py_newdict(dict);
+    c11__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) {
+        py_TValue* value = &locals[entry->value];
+        if(!py_isnil(value)) {
+            bool ok = py_dict_setitem(dict, py_name2ref(entry->key), value);
+            assert(ok);
+            (void)ok;
+        }
+    }
+    py_assign(py_retval(), dict);
+    py_pop();
 }
 
 NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
@@ -151,78 +160,62 @@ int Frame__delglobal(Frame* self, py_Name name) {
 
 int Frame__getlocal(Frame* self, py_Name name) {
     if(self->is_locals_proxy) {
-        py_StackRef p0 = py_peek(0);
-        py_push(self->locals);
-        py_pushmethod(__getitem__);
-        py_push(py_name2ref(name));
-        bool ok = py_vectorcall(1, 0);
-        if(!ok) {
-            if(py_matchexc(tp_KeyError)) {
-                py_clearexc(p0);
-                return 0;
-            }
-            return -1;
+        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));
         }
-        return 1;
-    } else {
-        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;
     }
+    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;
 }
 
-int Frame__setlocal(Frame* self, py_Name name, py_TValue* val) {
+bool Frame__setlocal(Frame* self, py_Name name, py_TValue* val) {
     if(self->is_locals_proxy) {
-        py_push(self->locals);
-        py_pushmethod(__setitem__);
-        py_push(py_name2ref(name));
-        py_push(val);
-        bool ok = py_vectorcall(2, 0);
-        if(!ok) return -1;
-        return 1;
-    } else {
-        py_Ref slot = Frame__getlocal_noproxy(self, name);
-        if(slot == NULL) return 0;  // bad slot
-        *slot = *val;
-        return 1;
+        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);
+        }
     }
+    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_proxy) {
-        py_StackRef p0 = py_peek(0);
-        py_push(self->locals);
-        py_pushmethod(__delitem__);
-        py_push(py_name2ref(name));
-        bool ok = py_vectorcall(1, 0);
-        if(!ok) {
-            if(py_matchexc(tp_KeyError)) {
-                py_clearexc(p0);
-                return 0;
-            }
-            return -1;
-        }
-        return 1;
-    } else {
-        py_Ref slot = Frame__getlocal_noproxy(self, name);
-        if(slot == NULL) return 0;  // bad slot
-        if(py_isnil(slot)) {
-            UnboundLocalError(name);
-            return -1;
+        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));
         }
-        py_newnil(slot);
-        return 1;
     }
+    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_proxy);
-    return FastLocals__try_get_by_name(self->locals, self->co, name);
+    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) {

+ 2 - 2
src/interpreter/vm.c

@@ -127,7 +127,7 @@ void VM__ctor(VM* self) {
     validate(tp_Exception, pk_Exception__register());
     validate(tp_bytes, pk_bytes__register());
     validate(tp_namedict, pk_namedict__register());
-    validate(tp_locals, pk_locals__register());
+    validate(tp_locals, pk_newtype("locals", tp_object, NULL, NULL, false, true));
     validate(tp_code, pk_code__register());
 
     validate(tp_dict, pk_dict__register());
@@ -258,7 +258,7 @@ void VM__dtor(VM* self) {
     ModuleDict__dtor(&self->modules);
     TypeList__dtor(&self->types);
     FixedMemoryPool__dtor(&self->pool_frame);
-    ValueStack__clear(&self->stack);
+    ValueStack__dtor(&self->stack);
     InternedNames__dtor(&self->names);
 }
 

+ 10 - 4
src/public/modules.c

@@ -511,11 +511,17 @@ void py_newlocals(py_Ref out) {
         py_newglobals(out);
         return;
     }
-    if(!frame->is_locals_proxy) {
-        pk_mappingproxy__locals(out, frame);
-    } else {
-        *out = *frame->locals;
+    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;
+        }
     }
+    FastLocals__to_dict(frame->locals, frame->co);
+    py_assign(out, py_retval());
 }
 
 static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_CompileMode mode) {

+ 0 - 56
src/public/py_mappingproxy.c

@@ -116,59 +116,3 @@ void pk_mappingproxy__locals(py_Ref out, Frame* frame) {
     // locals() will expire when the frame is destroyed
     out->_ptr = frame;
 }
-
-static bool locals__getitem__(int argc, py_Ref argv) {
-    PY_CHECK_ARGC(2);
-    PY_CHECK_ARG_TYPE(1, tp_str);
-    Frame* frame = argv->_ptr;
-    py_Name name = py_namev(py_tosv(py_arg(1)));
-    py_Ref slot = Frame__getlocal_noproxy(frame, name);
-    if(!slot || py_isnil(slot)) return KeyError(py_arg(1));
-    py_assign(py_retval(), slot);
-    return true;
-}
-
-static bool locals__setitem__(int argc, py_Ref argv) {
-    PY_CHECK_ARGC(3);
-    PY_CHECK_ARG_TYPE(1, tp_str);
-    Frame* frame = argv->_ptr;
-    py_Name name = py_namev(py_tosv(py_arg(1)));
-    py_Ref slot = Frame__getlocal_noproxy(frame, name);
-    if(!slot) return KeyError(py_arg(1));
-    py_assign(slot, py_arg(2));
-    py_newnone(py_retval());
-    return true;
-}
-
-static bool locals__delitem__(int argc, py_Ref argv) {
-    PY_CHECK_ARGC(2);
-    PY_CHECK_ARG_TYPE(1, tp_str);
-    Frame* frame = argv->_ptr;
-    py_Name name = py_namev(py_tosv(py_arg(1)));
-    py_Ref res = Frame__getlocal_noproxy(frame, name);
-    if(!res || py_isnil(res)) return KeyError(py_arg(1));
-    py_newnil(res);
-    py_newnone(py_retval());
-    return true;
-}
-
-static bool locals__contains__(int argc, py_Ref argv) {
-    PY_CHECK_ARGC(2);
-    PY_CHECK_ARG_TYPE(1, tp_str);
-    Frame* frame = argv->_ptr;
-    py_Name name = py_namev(py_tosv(py_arg(1)));
-    py_Ref slot = Frame__getlocal_noproxy(frame, name);
-    py_newbool(py_retval(), slot && !py_isnil(slot));
-    return true;
-}
-
-py_Type pk_locals__register() {
-    py_Type type = pk_newtype("locals", tp_object, NULL, NULL, false, true);
-
-    py_bindmagic(type, __getitem__, locals__getitem__);
-    py_bindmagic(type, __setitem__, locals__setitem__);
-    py_bindmagic(type, __delitem__, locals__delitem__);
-    py_bindmagic(type, __contains__, locals__contains__);
-    py_newnone(py_tpgetmagic(type, __hash__));
-    return type;
-}