mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-19 19:10:17 +00:00
backup
This commit is contained in:
parent
2d5561441d
commit
9af9d228dd
@ -57,10 +57,14 @@ 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;
|
||||
|
||||
py_Ref Frame__getclosure(Frame* self, py_Name name);
|
||||
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;
|
||||
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);
|
||||
|
||||
py_StackRef Frame__locals_sp(Frame* self);
|
||||
|
||||
int Frame__prepare_jump_exception_handler(Frame* self, ValueStack*);
|
||||
|
||||
|
@ -96,6 +96,7 @@ bool pk_loadmethod(py_StackRef self, py_Name name);
|
||||
bool pk_callmagic(py_Name name, int argc, py_Ref argv);
|
||||
|
||||
bool pk_exec(CodeObject* co, py_Ref module);
|
||||
bool pk_execdyn(CodeObject* co, py_Ref module, py_Ref globals, py_Ref locals);
|
||||
|
||||
/// Assumes [a, b] are on the stack, performs a binary op.
|
||||
/// The result is stored in `self->last_retval`.
|
||||
|
@ -194,6 +194,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
DISPATCH();
|
||||
/*****************************************/
|
||||
case OP_LOAD_FAST: {
|
||||
assert(!frame->is_locals_proxy);
|
||||
PUSH(&frame->locals[byte.arg]);
|
||||
if(py_isnil(TOP())) {
|
||||
py_Name name = c11__getitem(uint16_t, &frame->co->varnames, byte.arg);
|
||||
@ -220,7 +221,6 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// `LOAD_
|
||||
// globals
|
||||
if(py_getitem(&frame->p0[0], TOP())) {
|
||||
py_assign(TOP(), py_retval());
|
||||
@ -343,7 +343,11 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
TypeError("'%t' object is not subscriptable", SECOND()->type);
|
||||
goto __ERROR;
|
||||
}
|
||||
case OP_STORE_FAST: frame->locals[byte.arg] = POPX(); DISPATCH();
|
||||
case OP_STORE_FAST: {
|
||||
assert(!frame->is_locals_proxy);
|
||||
frame->locals[byte.arg] = POPX();
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_STORE_NAME: {
|
||||
// assert(frame->is_dynamic);
|
||||
py_Name name = byte.arg;
|
||||
@ -405,6 +409,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
goto __ERROR;
|
||||
}
|
||||
case OP_DELETE_FAST: {
|
||||
assert(!frame->is_locals_proxy);
|
||||
py_Ref tmp = &frame->locals[byte.arg];
|
||||
if(py_isnil(tmp)) {
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->varnames, byte.arg);
|
||||
|
@ -79,7 +79,7 @@ int Frame__prepare_jump_exception_handler(Frame* self, ValueStack* _s) {
|
||||
}
|
||||
if(iblock < 0) return -1;
|
||||
UnwindTarget* uw = Frame__find_unwind_target(self, iblock);
|
||||
_s->sp = (self->locals + uw->offset); // unwind the stack
|
||||
_s->sp = (Frame__locals_sp(self) + uw->offset); // unwind the stack
|
||||
return c11__at(CodeBlock, &self->co->blocks, iblock)->end;
|
||||
}
|
||||
|
||||
@ -95,10 +95,10 @@ void Frame__set_unwind_target(Frame* self, py_TValue* sp) {
|
||||
int iblock = Frame__iblock(self);
|
||||
UnwindTarget* existing = Frame__find_unwind_target(self, iblock);
|
||||
if(existing) {
|
||||
existing->offset = sp - self->locals;
|
||||
existing->offset = sp - Frame__locals_sp(self);
|
||||
} else {
|
||||
UnwindTarget* prev = self->uw_list;
|
||||
self->uw_list = UnwindTarget__new(prev, iblock, sp - self->locals);
|
||||
self->uw_list = UnwindTarget__new(prev, iblock, sp - Frame__locals_sp(self));
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,6 +149,77 @@ 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
int 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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
|
@ -28,10 +28,14 @@ static bool generator__next__(int argc, py_Ref argv) {
|
||||
if(ud->state == 2) return StopIteration();
|
||||
|
||||
// reset frame->p0
|
||||
int locals_offset = ud->frame->locals - ud->frame->p0;
|
||||
ud->frame->p0 = py_peek(0);
|
||||
ud->frame->locals = ud->frame->p0 + locals_offset;
|
||||
|
||||
if(!ud->frame->is_locals_proxy){
|
||||
int locals_offset = ud->frame->locals - ud->frame->p0;
|
||||
ud->frame->p0 = py_peek(0);
|
||||
ud->frame->locals = ud->frame->p0 + locals_offset;
|
||||
}else{
|
||||
ud->frame->p0 = py_peek(0);
|
||||
}
|
||||
|
||||
// restore the context
|
||||
py_Ref backup = py_getslot(argv, 0);
|
||||
int length = py_list_len(backup);
|
||||
|
@ -7,12 +7,11 @@
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
#include "pocketpy/compiler/compiler.h"
|
||||
|
||||
static void code__gc_mark(void* ud) { CodeObject__gc_mark(ud); }
|
||||
#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, code__gc_mark);
|
||||
pk__tp_set_marker(type, (void (*)(void *))CodeObject__gc_mark);
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -57,16 +56,34 @@ bool pk_exec(CodeObject* co, py_Ref module) {
|
||||
assert(module->type == tp_module);
|
||||
|
||||
py_StackRef sp = vm->stack.sp;
|
||||
if(co->src->is_dynamic) sp -= 3; // [globals, locals, code]
|
||||
|
||||
const bool is_p0_function = false;
|
||||
const bool is_locals_proxy = true;
|
||||
Frame* frame = Frame__new(co, sp, module, module, sp, is_p0_function, is_locals_proxy);
|
||||
Frame* frame = Frame__new(co, sp, module, module, sp, false, false);
|
||||
VM__push_frame(vm, frame);
|
||||
FrameResult res = VM__run_top_frame(vm);
|
||||
if(res == RES_ERROR) return false;
|
||||
if(res == RES_RETURN) return true;
|
||||
c11__unreachable();
|
||||
assert(res == RES_RETURN);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pk_execdyn(CodeObject* co, py_Ref module, py_Ref globals, py_Ref locals) {
|
||||
VM* vm = pk_current_vm;
|
||||
if(!module) module = &vm->main;
|
||||
assert(module->type == tp_module);
|
||||
|
||||
py_StackRef sp = vm->stack.sp;
|
||||
assert(globals != NULL && locals != NULL);
|
||||
|
||||
if(globals->type == tp_namedict) {
|
||||
globals = py_getslot(globals, 0);
|
||||
assert(globals->type == tp_module);
|
||||
} else {
|
||||
assert(globals->type == tp_dict);
|
||||
}
|
||||
Frame* frame = Frame__new(co, sp, module, globals, locals, false, true);
|
||||
VM__push_frame(vm, frame);
|
||||
FrameResult res = VM__run_top_frame(vm);
|
||||
if(res == RES_ERROR) return false;
|
||||
assert(res == RES_RETURN);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
|
||||
|
@ -501,7 +501,7 @@ void py_newglobals(py_Ref out) {
|
||||
if(frame->globals->type == tp_module) {
|
||||
pk_mappingproxy__namedict(out, frame->globals);
|
||||
} else {
|
||||
*out = *frame->globals; // dict
|
||||
*out = *frame->globals; // dict
|
||||
}
|
||||
}
|
||||
|
||||
@ -511,9 +511,9 @@ void py_newlocals(py_Ref out) {
|
||||
py_newglobals(out);
|
||||
return;
|
||||
}
|
||||
if(!frame->is_locals_proxy){
|
||||
if(!frame->is_locals_proxy) {
|
||||
pk_mappingproxy__locals(out, frame);
|
||||
}else{
|
||||
} else {
|
||||
*out = *frame->locals;
|
||||
}
|
||||
}
|
||||
@ -529,6 +529,7 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_
|
||||
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();
|
||||
@ -538,6 +539,7 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_
|
||||
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));
|
||||
@ -562,12 +564,15 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_
|
||||
// [globals, locals, code]
|
||||
CodeObject* co = py_touserdata(code);
|
||||
if(!co->src->is_dynamic) {
|
||||
py_shrink(3);
|
||||
if(argc != 1)
|
||||
return ValueError("code object is not dynamic, `globals` and `locals` must be None");
|
||||
py_shrink(3);
|
||||
}
|
||||
|
||||
Frame* frame = pk_current_vm->top_frame;
|
||||
return pk_exec(co, frame ? frame->module : NULL);
|
||||
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) {
|
||||
@ -787,7 +792,9 @@ static bool super__new__(int argc, py_Ref argv) {
|
||||
Function* func = py_touserdata(callable);
|
||||
if(func->clazz != NULL) {
|
||||
class_arg = *(py_Type*)PyObject__userdata(func->clazz);
|
||||
if(frame->co->nlocals > 0) self_arg = &frame->locals[0];
|
||||
if(frame->co->nlocals > 0) {
|
||||
if(!frame->is_locals_proxy) self_arg = &frame->locals[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user