This commit is contained in:
blueloveTH 2025-02-28 16:25:22 +08:00
parent d160d79d3f
commit bf7bfa938c
4 changed files with 81 additions and 104 deletions

View File

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

View File

@ -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);
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 == -1) goto __ERROR;
// closure
py_Ref tmp = Frame__getclosure(frame, name);
if(tmp != NULL) {
PUSH(tmp);
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,22 +360,32 @@ 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 {
case tp_nil: {
// globals
if(!Frame__setglobal(frame, name, TOP())) { goto __ERROR; }
if(!Frame__setglobal(frame, name, TOP())) goto __ERROR;
POP();
DISPATCH();
}
default: c11__unreachable();
}
}
case OP_STORE_GLOBAL: {
if(!Frame__setglobal(frame, byte.arg, TOP())) goto __ERROR;
@ -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);
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;
} else {
}
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;
DISPATCH();
}
default: c11__unreachable();
}
}
case OP_DELETE_GLOBAL: {

View File

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

View File

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