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; 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__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_Ref Frame__getclosure(Frame* self, py_Name name);
py_StackRef Frame__getlocal_noproxy(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(); DISPATCH();
} }
case OP_LOAD_NAME: { case OP_LOAD_NAME: {
assert(frame->is_locals_special);
py_Name name = byte.arg; py_Name name = byte.arg;
// locals // locals
int res = Frame__getlocal(frame, name); switch(frame->locals->type) {
if(res == 1) { case tp_locals: {
PUSH(&self->last_retval); Frame* noproxy = frame->locals->_ptr;
DISPATCH(); py_Ref slot = Frame__getlocal_noproxy(noproxy, name);
} if(slot == NULL) break;
if(res == -1) goto __ERROR; if(py_isnil(slot)) {
// closure UnboundLocalError(name);
py_Ref tmp = Frame__getclosure(frame, name); goto __ERROR;
if(tmp != NULL) { }
PUSH(tmp); PUSH(slot);
DISPATCH(); 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 // globals
res = Frame__getglobal(frame, name); int res = Frame__getglobal(frame, name);
if(res == 1) { if(res == 1) {
PUSH(&self->last_retval); PUSH(&self->last_retval);
DISPATCH(); DISPATCH();
} }
if(res == -1) goto __ERROR; if(res == -1) goto __ERROR;
// builtins // builtins
tmp = py_getdict(&self->builtins, name); py_Ref tmp = py_getdict(&self->builtins, name);
if(tmp != NULL) { if(tmp != NULL) {
PUSH(tmp); PUSH(tmp);
DISPATCH(); DISPATCH();
@ -346,21 +360,31 @@ FrameResult VM__run_top_frame(VM* self) {
DISPATCH(); DISPATCH();
} }
case OP_STORE_NAME: { case OP_STORE_NAME: {
assert(frame->is_locals_special);
py_Name name = byte.arg; py_Name name = byte.arg;
if(frame->locals != NULL) { switch(frame->locals->type) {
// locals case tp_locals: {
int res = Frame__setlocal(frame, name, TOP()); Frame* noproxy = frame->locals->_ptr;
if(res == 1) { 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(); POP();
DISPATCH(); DISPATCH();
} }
if(res == 0) NameError(name); case tp_nil: {
goto __ERROR; // globals
} else { if(!Frame__setglobal(frame, name, TOP())) goto __ERROR;
// globals POP();
if(!Frame__setglobal(frame, name, TOP())) { goto __ERROR; } DISPATCH();
POP(); }
DISPATCH(); default: c11__unreachable();
} }
} }
case OP_STORE_GLOBAL: { case OP_STORE_GLOBAL: {
@ -403,20 +427,33 @@ FrameResult VM__run_top_frame(VM* self) {
DISPATCH(); DISPATCH();
} }
case OP_DELETE_NAME: { case OP_DELETE_NAME: {
assert(frame->is_locals_special);
py_Name name = byte.arg; py_Name name = byte.arg;
if(frame->locals != NULL) { switch(frame->locals->type) {
// locals case tp_locals: {
int res = Frame__dellocal(frame, name); Frame* noproxy = frame->locals->_ptr;
if(res == 1) DISPATCH(); py_Ref slot = Frame__getlocal_noproxy(noproxy, name);
if(res == 0) NameError(name); if(slot == NULL || py_isnil(slot)) {
goto __ERROR; UnboundLocalError(name);
} else { goto __ERROR;
// globals }
int res = Frame__delglobal(frame, name); py_newnil(slot);
if(res == 1) DISPATCH(); DISPATCH();
if(res == 0) NameError(name); }
goto __ERROR; case tp_dict: {
DISPATCH(); 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: { 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) { py_StackRef Frame__getlocal_noproxy(Frame* self, py_Name name) {
assert(!self->is_locals_special); assert(!self->is_locals_special);
int index = c11_smallmap_n2i__get(&self->co->varnames_inv, name, -1); 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()); py_assign(out, py_retval());
} }
static void pk_push_locals_proxy() { static void pk_push_special_locals() {
Frame* frame = pk_current_vm->top_frame; Frame* frame = pk_current_vm->top_frame;
if(!frame) { if(!frame) {
py_pushnil(); py_pushnil();
@ -546,7 +546,7 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_
switch(argc) { switch(argc) {
case 1: { case 1: {
py_newglobals(py_pushtmp()); py_newglobals(py_pushtmp());
pk_push_locals_proxy(); pk_push_special_locals();
break; break;
} }
case 2: { 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)); py_push(py_arg(1));
} }
// locals // locals
pk_push_locals_proxy(); pk_push_special_locals();
break; break;
} }
case 3: { case 3: {
@ -571,7 +571,7 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_
} }
// locals // locals
if(py_isnone(py_arg(2))) { if(py_isnone(py_arg(2))) {
pk_push_locals_proxy(); pk_push_special_locals();
} else { } else {
if(!py_checktype(py_arg(2), tp_dict)) return false; if(!py_checktype(py_arg(2), tp_dict)) return false;
py_push(py_arg(2)); 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); default: return TypeError("%s() takes at most 3 arguments", title);
} }
py_Ref tmp_code;
if(py_isstr(argv)) { if(py_isstr(argv)) {
bool ok = py_compile(py_tostr(argv), "<string>", mode, true); bool ok = py_compile(py_tostr(argv), "<string>", mode, true);
if(!ok) return false; if(!ok) return false;
tmp_code = py_retval(); py_push(py_retval());
} else if(py_istype(argv, tp_code)) { } else if(py_istype(argv, tp_code)) {
tmp_code = argv; py_push(argv);
} else { } else {
return TypeError("%s() expected 'str' or 'code', got '%t'", title, argv->type); 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; Frame* frame = pk_current_vm->top_frame;
// [globals, locals, code] // [globals, locals, code]
CodeObject* code = py_touserdata(tmp_code); CodeObject* code = py_touserdata(py_peek(-1));
if(code->src->is_dynamic) { if(code->src->is_dynamic) {
bool ok = pk_execdyn(code, frame ? frame->module : NULL, py_peek(-3), py_peek(-2)); bool ok = pk_execdyn(code, frame ? frame->module : NULL, py_peek(-3), py_peek(-2));
py_shrink(3); py_shrink(3);