This commit is contained in:
blueloveTH 2025-02-27 19:51:13 +08:00
parent f941d26845
commit 96ff66ef69
6 changed files with 97 additions and 114 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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