This commit is contained in:
blueloveTH 2024-08-06 13:47:41 +08:00
parent f756bd813d
commit 749435e516
8 changed files with 71 additions and 36 deletions

View File

@ -6,6 +6,7 @@
#include "pocketpy/objects/object.h" #include "pocketpy/objects/object.h"
#include "pocketpy/common/config.h" #include "pocketpy/common/config.h"
#include "pocketpy/common/strname.h" #include "pocketpy/common/strname.h"
#include "pocketpy/pocketpy.h"
py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co, py_Name name); py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co, py_Name name);
NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co); NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
@ -34,7 +35,7 @@ typedef struct Frame {
struct Frame* f_back; struct Frame* f_back;
const Bytecode* ip; const Bytecode* ip;
const CodeObject* co; const CodeObject* co;
py_TValue module; // weak ref py_GlobalRef module;
py_StackRef function; // a function object or NULL (global scope) py_StackRef function; // a function object or NULL (global scope)
py_StackRef p0; // unwinding base py_StackRef p0; // unwinding base
py_StackRef locals; // locals base py_StackRef locals; // locals base
@ -42,7 +43,7 @@ typedef struct Frame {
} Frame; } Frame;
Frame* Frame__new(const CodeObject* co, Frame* Frame__new(const CodeObject* co,
py_TValue* module, py_GlobalRef module,
py_StackRef function, py_StackRef function,
py_StackRef p0, py_StackRef p0,
py_StackRef locals); py_StackRef locals);

View File

@ -1,2 +1,10 @@
#pragma once #pragma once
#include "pocketpy/interpreter/frame.h"
typedef struct Generator{
Frame* frame;
int state;
} Generator;
void pk_newgenerator(py_Ref out, Frame* frame, int slots);

View File

@ -518,9 +518,10 @@ enum py_PredefinedTypes {
tp_NoneType, tp_NoneType,
tp_NotImplementedType, tp_NotImplementedType,
tp_ellipsis, tp_ellipsis,
tp_SyntaxError, tp_generator,
tp_StopIteration,
/* builtin exceptions */ /* builtin exceptions */
tp_StopIteration,
tp_SyntaxError,
tp_StackOverflowError, tp_StackOverflowError,
tp_IOError, tp_IOError,
tp_OSError, tp_OSError,

View File

@ -134,7 +134,7 @@ FrameResult VM__run_top_frame(VM* self) {
case OP_LOAD_FUNCTION: { case OP_LOAD_FUNCTION: {
FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg); FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
Function* ud = py_newobject(SP(), tp_function, 0, sizeof(Function)); Function* ud = py_newobject(SP(), tp_function, 0, sizeof(Function));
Function__ctor(ud, decl, &frame->module); Function__ctor(ud, decl, frame->module);
if(decl->nested) { if(decl->nested) {
ud->closure = FastLocals__to_namedict(frame->locals, frame->co); ud->closure = FastLocals__to_namedict(frame->locals, frame->co);
py_Name name = py_name(decl->code.name->data); py_Name name = py_name(decl->code.name->data);
@ -173,7 +173,7 @@ FrameResult VM__run_top_frame(VM* self) {
PUSH(tmp); PUSH(tmp);
DISPATCH(); DISPATCH();
} }
tmp = py_getdict(&frame->module, name); tmp = py_getdict(frame->module, name);
if(tmp != NULL) { if(tmp != NULL) {
PUSH(tmp); PUSH(tmp);
DISPATCH(); DISPATCH();
@ -193,7 +193,7 @@ FrameResult VM__run_top_frame(VM* self) {
PUSH(tmp); PUSH(tmp);
DISPATCH(); DISPATCH();
} }
tmp = py_getdict(&frame->module, name); tmp = py_getdict(frame->module, name);
if(tmp != NULL) { if(tmp != NULL) {
PUSH(tmp); PUSH(tmp);
DISPATCH(); DISPATCH();
@ -208,7 +208,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
case OP_LOAD_GLOBAL: { case OP_LOAD_GLOBAL: {
py_Name name = byte.arg; py_Name name = byte.arg;
py_Ref tmp = py_getdict(&frame->module, name); py_Ref tmp = py_getdict(frame->module, name);
if(tmp != NULL) { if(tmp != NULL) {
PUSH(tmp); PUSH(tmp);
DISPATCH(); DISPATCH();
@ -237,7 +237,7 @@ FrameResult VM__run_top_frame(VM* self) {
DISPATCH(); DISPATCH();
} }
// load global if attribute not found // load global if attribute not found
tmp = py_getdict(&frame->module, name); tmp = py_getdict(frame->module, name);
if(tmp) { if(tmp) {
PUSH(tmp); PUSH(tmp);
DISPATCH(); DISPATCH();
@ -300,13 +300,13 @@ FrameResult VM__run_top_frame(VM* self) {
// } // }
} }
} else { } else {
py_setdict(&frame->module, name, TOP()); py_setdict(frame->module, name, TOP());
} }
POP(); POP();
DISPATCH(); DISPATCH();
} }
case OP_STORE_GLOBAL: { case OP_STORE_GLOBAL: {
py_setdict(&frame->module, byte.arg, TOP()); py_setdict(frame->module, byte.arg, TOP());
POP(); POP();
DISPATCH(); DISPATCH();
} }
@ -361,7 +361,7 @@ FrameResult VM__run_top_frame(VM* self) {
// } // }
} }
} else { } else {
bool ok = py_deldict(&frame->module, name); bool ok = py_deldict(frame->module, name);
if(!ok) { if(!ok) {
NameError(name); NameError(name);
goto __ERROR; goto __ERROR;
@ -371,7 +371,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
case OP_DELETE_GLOBAL: { case OP_DELETE_GLOBAL: {
py_Name name = byte.arg; py_Name name = byte.arg;
bool ok = py_deldict(&frame->module, name); bool ok = py_deldict(frame->module, name);
if(!ok) { if(!ok) {
NameError(name); NameError(name);
goto __ERROR; goto __ERROR;
@ -802,7 +802,7 @@ FrameResult VM__run_top_frame(VM* self) {
ImportError("cannot import name '%n'", name); ImportError("cannot import name '%n'", name);
goto __ERROR; goto __ERROR;
} else { } else {
py_setdict(&frame->module, name, value); py_setdict(frame->module, name, value);
} }
} }
} else { } else {
@ -811,7 +811,7 @@ FrameResult VM__run_top_frame(VM* self) {
if(!kv->key) continue; if(!kv->key) continue;
c11_sv name = py_name2sv(kv->key); c11_sv name = py_name2sv(kv->key);
if(name.size == 0 || name.data[0] == '_') continue; if(name.size == 0 || name.data[0] == '_') continue;
py_setdict(&frame->module, kv->key, &kv->value); py_setdict(frame->module, kv->key, &kv->value);
} }
} }
POP(); POP();
@ -857,7 +857,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
POP(); POP();
py_Type type = py_Type type =
pk_newtype(py_name2str(name), base, &frame->module, NULL, true, false); pk_newtype(py_name2str(name), base, frame->module, NULL, true, false);
PUSH(py_tpobject(type)); PUSH(py_tpobject(type));
self->__curr_class = TOP(); self->__curr_class = TOP();
DISPATCH(); DISPATCH();
@ -866,7 +866,7 @@ FrameResult VM__run_top_frame(VM* self) {
// [cls or decorated] // [cls or decorated]
py_Name name = byte.arg; py_Name name = byte.arg;
// set into f_globals // set into f_globals
py_setdict(&frame->module, name, TOP()); py_setdict(frame->module, name, TOP());
if(py_istype(TOP(), tp_type)) { if(py_istype(TOP(), tp_type)) {
// call on_end_subclass // call on_end_subclass
@ -950,7 +950,7 @@ FrameResult VM__run_top_frame(VM* self) {
py_TValue* tmp = c11__at(py_TValue, &frame->co->consts, byte.arg); py_TValue* tmp = c11__at(py_TValue, &frame->co->consts, byte.arg);
const char* string = py_tostr(tmp); const char* string = py_tostr(tmp);
// TODO: optimize this // TODO: optimize this
if(!py_exec(string, "<eval>", EVAL_MODE, &frame->module)) goto __ERROR; if(!py_exec(string, "<eval>", EVAL_MODE, frame->module)) goto __ERROR;
PUSH(py_retval()); PUSH(py_retval());
DISPATCH(); DISPATCH();
} }

View File

@ -1,6 +1,7 @@
#include "pocketpy/interpreter/frame.h" #include "pocketpy/interpreter/frame.h"
#include "pocketpy/objects/codeobject.h" #include "pocketpy/objects/codeobject.h"
#include "pocketpy/objects/object.h" #include "pocketpy/objects/object.h"
#include "pocketpy/pocketpy.h"
void ValueStack__ctor(ValueStack* self) { void ValueStack__ctor(ValueStack* self) {
self->sp = self->begin; self->sp = self->begin;
@ -35,7 +36,7 @@ UnwindTarget* UnwindTarget__new(UnwindTarget* next, int iblock, int offset) {
void UnwindTarget__delete(UnwindTarget* self) { free(self); } void UnwindTarget__delete(UnwindTarget* self) { free(self); }
Frame* Frame__new(const CodeObject* co, Frame* Frame__new(const CodeObject* co,
py_TValue* module, py_GlobalRef module,
py_StackRef function, py_StackRef function,
py_StackRef p0, py_StackRef p0,
py_StackRef locals) { py_StackRef locals) {
@ -44,7 +45,7 @@ Frame* Frame__new(const CodeObject* co,
self->f_back = NULL; self->f_back = NULL;
self->ip = (Bytecode*)co->codes.data - 1; self->ip = (Bytecode*)co->codes.data - 1;
self->co = co; self->co = co;
self->module = *module; self->module = module;
self->function = function; self->function = function;
self->p0 = p0; self->p0 = p0;
self->locals = locals; self->locals = locals;

View File

@ -1 +1,8 @@
#include "pocketpy/interpreter/generator.h" #include "pocketpy/interpreter/generator.h"
#include "pocketpy/interpreter/frame.h"
void pk_newgenerator(py_Ref out, Frame* frame, int slots) {
Generator* ud = py_newobject(out, tp_generator, slots, sizeof(Generator));
ud->frame = frame;
ud->state = 0;
}

View File

@ -2,6 +2,7 @@
#include "pocketpy/common/memorypool.h" #include "pocketpy/common/memorypool.h"
#include "pocketpy/common/sstream.h" #include "pocketpy/common/sstream.h"
#include "pocketpy/common/utils.h" #include "pocketpy/common/utils.h"
#include "pocketpy/interpreter/generator.h"
#include "pocketpy/objects/base.h" #include "pocketpy/objects/base.h"
#include "pocketpy/common/_generated.h" #include "pocketpy/common/_generated.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
@ -126,9 +127,7 @@ void VM__ctor(VM* self) {
validate(tp_NotImplementedType, validate(tp_NotImplementedType,
pk_newtype("NotImplementedType", tp_object, NULL, NULL, false, true)); pk_newtype("NotImplementedType", tp_object, NULL, NULL, false, true));
validate(tp_ellipsis, pk_newtype("ellipsis", tp_object, NULL, NULL, false, true)); validate(tp_ellipsis, pk_newtype("ellipsis", tp_object, NULL, NULL, false, true));
validate(tp_generator, pk_newtype("generator", tp_object, NULL, NULL, false, true));
validate(tp_SyntaxError, pk_newtype("SyntaxError", tp_Exception, NULL, NULL, false, true));
validate(tp_StopIteration, pk_newtype("StopIteration", tp_Exception, NULL, NULL, false, true));
self->builtins = pk_builtins__register(); self->builtins = pk_builtins__register();
@ -140,6 +139,8 @@ void VM__ctor(VM* self) {
validate(tp_##name, type); \ validate(tp_##name, type); \
} while(0) } while(0)
INJECT_BUILTIN_EXC(StopIteration);
INJECT_BUILTIN_EXC(SyntaxError);
INJECT_BUILTIN_EXC(StackOverflowError); INJECT_BUILTIN_EXC(StackOverflowError);
INJECT_BUILTIN_EXC(IOError); INJECT_BUILTIN_EXC(IOError);
INJECT_BUILTIN_EXC(OSError); INJECT_BUILTIN_EXC(OSError);
@ -160,11 +161,26 @@ void VM__ctor(VM* self) {
#undef validate #undef validate
/* Setup Public Builtin Types */ /* Setup Public Builtin Types */
py_Type public_types[] = {tp_object, tp_type, tp_int, tp_float, py_Type public_types[] = {
tp_bool, tp_str, tp_list, tp_tuple, tp_object,
tp_slice, tp_range, tp_bytes, tp_dict, tp_type,
tp_property, tp_staticmethod, tp_classmethod, tp_super, tp_int,
tp_BaseException, tp_Exception, tp_StopIteration, tp_SyntaxError}; tp_float,
tp_bool,
tp_str,
tp_list,
tp_tuple,
tp_slice,
tp_range,
tp_bytes,
tp_dict,
tp_property,
tp_staticmethod,
tp_classmethod,
tp_super,
tp_BaseException,
tp_Exception,
};
for(int i = 0; i < c11__count_array(public_types); i++) { for(int i = 0; i < c11__count_array(public_types); i++) {
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, public_types[i]); py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, public_types[i]);
@ -438,6 +454,9 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
case FuncType_GENERATOR: { case FuncType_GENERATOR: {
bool ok = prepare_py_call(self->__vectorcall_buffer, argv, p1, kwargc, fn->decl); bool ok = prepare_py_call(self->__vectorcall_buffer, argv, p1, kwargc, fn->decl);
if(!ok) return RES_ERROR; if(!ok) return RES_ERROR;
Frame* frame = Frame__new(co, &fn->module, p0, p0, argv);
pk_newgenerator(py_retval(), frame, 0);
self->stack.sp = p0;
return RES_RETURN; return RES_RETURN;
} }
// prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl); // prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
@ -560,7 +579,7 @@ void ManagedHeap__mark(ManagedHeap* self) {
} }
// mark frame // mark frame
for(Frame* frame = vm->top_frame; frame; frame = frame->f_back) { for(Frame* frame = vm->top_frame; frame; frame = frame->f_back) {
mark_value(&frame->module); mark_value(frame->module);
} }
// mark vm's registers // mark vm's registers
mark_value(&vm->last_retval); mark_value(&vm->last_retval);

View File

@ -68,7 +68,7 @@ int py_import(const char* path_cstr) {
c11_sv top_filename = c11_string__sv(vm->top_frame->co->src->filename); c11_sv top_filename = c11_string__sv(vm->top_frame->co->src->filename);
int is_init = c11_sv__endswith(top_filename, (c11_sv){"__init__.py", 11}); int is_init = c11_sv__endswith(top_filename, (c11_sv){"__init__.py", 11});
py_Ref package = py_getdict(&vm->top_frame->module, __path__); py_Ref package = py_getdict(vm->top_frame->module, __path__);
c11_sv package_sv = py_tosv(package); c11_sv package_sv = py_tosv(package);
if(package_sv.size == 0) { if(package_sv.size == 0) {
return ImportError("attempted relative import with no known parent package"); return ImportError("attempted relative import with no known parent package");
@ -323,14 +323,14 @@ static bool builtins_exec(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str); PY_CHECK_ARG_TYPE(0, tp_str);
Frame* frame = pk_current_vm->top_frame; Frame* frame = pk_current_vm->top_frame;
return py_exec(py_tostr(argv), "<exec>", EXEC_MODE, &frame->module); return py_exec(py_tostr(argv), "<exec>", EXEC_MODE, frame->module);
} }
static bool builtins_eval(int argc, py_Ref argv) { static bool builtins_eval(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str); PY_CHECK_ARG_TYPE(0, tp_str);
Frame* frame = pk_current_vm->top_frame; Frame* frame = pk_current_vm->top_frame;
return py_exec(py_tostr(argv), "<eval>", EVAL_MODE, &frame->module); return py_exec(py_tostr(argv), "<eval>", EVAL_MODE, frame->module);
} }
static bool builtins_isinstance(int argc, py_Ref argv) { static bool builtins_isinstance(int argc, py_Ref argv) {
@ -418,9 +418,7 @@ static bool builtins_chr(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_int); PY_CHECK_ARG_TYPE(0, tp_int);
py_i64 val = py_toint(py_arg(0)); py_i64 val = py_toint(py_arg(0));
if(val < 0 || val > 128) { if(val < 0 || val > 128) { return ValueError("chr() arg not in range(128)"); }
return ValueError("chr() arg not in range(128)");
}
py_newstrn(py_retval(), (const char*)&val, 1); py_newstrn(py_retval(), (const char*)&val, 1);
return true; return true;
} }