mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-22 12:30:19 +00:00
...
This commit is contained in:
parent
f756bd813d
commit
749435e516
@ -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);
|
||||||
|
@ -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);
|
@ -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,
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
}
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user