This commit is contained in:
blueloveTH 2025-02-27 13:21:55 +08:00
parent 9af9d228dd
commit 2ba131a252
7 changed files with 69 additions and 128 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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 *************/

View File

@ -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;
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));
}
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_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) {

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;
}