mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +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;
|
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;
|
||||||
|
|
||||||
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__getlocal_noproxy(Frame* self, py_Name name);
|
||||||
|
|
||||||
|
py_StackRef Frame__locals_sp(Frame* self);
|
||||||
|
|
||||||
int Frame__prepare_jump_exception_handler(Frame* self, ValueStack*);
|
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_callmagic(py_Name name, int argc, py_Ref argv);
|
||||||
|
|
||||||
bool pk_exec(CodeObject* co, py_Ref module);
|
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.
|
/// Assumes [a, b] are on the stack, performs a binary op.
|
||||||
/// The result is stored in `self->last_retval`.
|
/// The result is stored in `self->last_retval`.
|
||||||
|
@ -194,6 +194,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
|||||||
DISPATCH();
|
DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_LOAD_FAST: {
|
case OP_LOAD_FAST: {
|
||||||
|
assert(!frame->is_locals_proxy);
|
||||||
PUSH(&frame->locals[byte.arg]);
|
PUSH(&frame->locals[byte.arg]);
|
||||||
if(py_isnil(TOP())) {
|
if(py_isnil(TOP())) {
|
||||||
py_Name name = c11__getitem(uint16_t, &frame->co->varnames, byte.arg);
|
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
|
// globals
|
||||||
if(py_getitem(&frame->p0[0], TOP())) {
|
if(py_getitem(&frame->p0[0], TOP())) {
|
||||||
py_assign(TOP(), py_retval());
|
py_assign(TOP(), py_retval());
|
||||||
@ -343,7 +343,11 @@ FrameResult VM__run_top_frame(VM* self) {
|
|||||||
TypeError("'%t' object is not subscriptable", SECOND()->type);
|
TypeError("'%t' object is not subscriptable", SECOND()->type);
|
||||||
goto __ERROR;
|
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: {
|
case OP_STORE_NAME: {
|
||||||
// assert(frame->is_dynamic);
|
// assert(frame->is_dynamic);
|
||||||
py_Name name = byte.arg;
|
py_Name name = byte.arg;
|
||||||
@ -405,6 +409,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
|||||||
goto __ERROR;
|
goto __ERROR;
|
||||||
}
|
}
|
||||||
case OP_DELETE_FAST: {
|
case OP_DELETE_FAST: {
|
||||||
|
assert(!frame->is_locals_proxy);
|
||||||
py_Ref tmp = &frame->locals[byte.arg];
|
py_Ref tmp = &frame->locals[byte.arg];
|
||||||
if(py_isnil(tmp)) {
|
if(py_isnil(tmp)) {
|
||||||
py_Name name = c11__getitem(py_Name, &frame->co->varnames, byte.arg);
|
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;
|
if(iblock < 0) return -1;
|
||||||
UnwindTarget* uw = Frame__find_unwind_target(self, iblock);
|
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;
|
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);
|
int iblock = Frame__iblock(self);
|
||||||
UnwindTarget* existing = Frame__find_unwind_target(self, iblock);
|
UnwindTarget* existing = Frame__find_unwind_target(self, iblock);
|
||||||
if(existing) {
|
if(existing) {
|
||||||
existing->offset = sp - self->locals;
|
existing->offset = sp - Frame__locals_sp(self);
|
||||||
} else {
|
} else {
|
||||||
UnwindTarget* prev = self->uw_list;
|
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) {
|
py_StackRef Frame__getlocal_noproxy(Frame* self, py_Name name) {
|
||||||
assert(!self->is_locals_proxy);
|
assert(!self->is_locals_proxy);
|
||||||
return FastLocals__try_get_by_name(self->locals, self->co, name);
|
return FastLocals__try_get_by_name(self->locals, self->co, name);
|
||||||
|
@ -28,9 +28,13 @@ static bool generator__next__(int argc, py_Ref argv) {
|
|||||||
if(ud->state == 2) return StopIteration();
|
if(ud->state == 2) return StopIteration();
|
||||||
|
|
||||||
// reset frame->p0
|
// reset frame->p0
|
||||||
|
if(!ud->frame->is_locals_proxy){
|
||||||
int locals_offset = ud->frame->locals - ud->frame->p0;
|
int locals_offset = ud->frame->locals - ud->frame->p0;
|
||||||
ud->frame->p0 = py_peek(0);
|
ud->frame->p0 = py_peek(0);
|
||||||
ud->frame->locals = ud->frame->p0 + locals_offset;
|
ud->frame->locals = ud->frame->p0 + locals_offset;
|
||||||
|
}else{
|
||||||
|
ud->frame->p0 = py_peek(0);
|
||||||
|
}
|
||||||
|
|
||||||
// restore the context
|
// restore the context
|
||||||
py_Ref backup = py_getslot(argv, 0);
|
py_Ref backup = py_getslot(argv, 0);
|
||||||
|
@ -7,12 +7,11 @@
|
|||||||
#include "pocketpy/objects/object.h"
|
#include "pocketpy/objects/object.h"
|
||||||
#include "pocketpy/interpreter/vm.h"
|
#include "pocketpy/interpreter/vm.h"
|
||||||
#include "pocketpy/compiler/compiler.h"
|
#include "pocketpy/compiler/compiler.h"
|
||||||
|
#include <assert.h>
|
||||||
static void code__gc_mark(void* ud) { CodeObject__gc_mark(ud); }
|
|
||||||
|
|
||||||
py_Type pk_code__register() {
|
py_Type pk_code__register() {
|
||||||
py_Type type = pk_newtype("code", tp_object, NULL, (py_Dtor)CodeObject__dtor, false, true);
|
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;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,16 +56,34 @@ bool pk_exec(CodeObject* co, py_Ref module) {
|
|||||||
assert(module->type == tp_module);
|
assert(module->type == tp_module);
|
||||||
|
|
||||||
py_StackRef sp = vm->stack.sp;
|
py_StackRef sp = vm->stack.sp;
|
||||||
if(co->src->is_dynamic) sp -= 3; // [globals, locals, code]
|
Frame* frame = Frame__new(co, sp, module, module, sp, false, false);
|
||||||
|
|
||||||
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);
|
|
||||||
VM__push_frame(vm, frame);
|
VM__push_frame(vm, frame);
|
||||||
FrameResult res = VM__run_top_frame(vm);
|
FrameResult res = VM__run_top_frame(vm);
|
||||||
if(res == RES_ERROR) return false;
|
if(res == RES_ERROR) return false;
|
||||||
if(res == RES_RETURN) return true;
|
assert(res == RES_RETURN);
|
||||||
c11__unreachable();
|
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) {
|
bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
|
||||||
|
@ -529,6 +529,7 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_
|
|||||||
if(py_isnone(py_arg(1))) {
|
if(py_isnone(py_arg(1))) {
|
||||||
py_newglobals(py_pushtmp());
|
py_newglobals(py_pushtmp());
|
||||||
} else {
|
} else {
|
||||||
|
if(!py_checktype(py_arg(1), tp_dict)) return false;
|
||||||
py_push(py_arg(1));
|
py_push(py_arg(1));
|
||||||
}
|
}
|
||||||
py_pushnone();
|
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))) {
|
if(py_isnone(py_arg(1))) {
|
||||||
py_newglobals(py_pushtmp());
|
py_newglobals(py_pushtmp());
|
||||||
} else {
|
} else {
|
||||||
|
if(!py_checktype(py_arg(1), tp_dict)) return false;
|
||||||
py_push(py_arg(1));
|
py_push(py_arg(1));
|
||||||
}
|
}
|
||||||
py_push(py_arg(2));
|
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]
|
// [globals, locals, code]
|
||||||
CodeObject* co = py_touserdata(code);
|
CodeObject* co = py_touserdata(code);
|
||||||
if(!co->src->is_dynamic) {
|
if(!co->src->is_dynamic) {
|
||||||
|
py_shrink(3);
|
||||||
if(argc != 1)
|
if(argc != 1)
|
||||||
return ValueError("code object is not dynamic, `globals` and `locals` must be None");
|
return ValueError("code object is not dynamic, `globals` and `locals` must be None");
|
||||||
py_shrink(3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame* frame = pk_current_vm->top_frame;
|
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) {
|
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);
|
Function* func = py_touserdata(callable);
|
||||||
if(func->clazz != NULL) {
|
if(func->clazz != NULL) {
|
||||||
class_arg = *(py_Type*)PyObject__userdata(func->clazz);
|
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