This commit is contained in:
blueloveTH 2024-08-08 14:08:17 +08:00
parent 81edd22a76
commit 4829568c87
11 changed files with 48 additions and 13 deletions

View File

@ -50,3 +50,9 @@
#else #else
#define PK_PLATFORM_SEP '/' #define PK_PLATFORM_SEP '/'
#endif #endif
#ifdef NDEBUG
#define PK_DEBUG 0
#else
#define PK_DEBUG 1
#endif

View File

@ -304,7 +304,7 @@ bool py_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
/// Python equivalent to `del self[key]`. /// Python equivalent to `del self[key]`.
bool py_delitem(py_Ref self, py_Ref key) PY_RAISE; bool py_delitem(py_Ref self, py_Ref key) PY_RAISE;
/// Perform a binary operation on the stack. /// Perform a binary operation.
/// The result will be set to `py_retval()`. /// The result will be set to `py_retval()`.
/// The stack remains unchanged after the operation. /// The stack remains unchanged after the operation.
bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) PY_RAISE; bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) PY_RAISE;
@ -431,6 +431,14 @@ bool py_isidentical(py_Ref, py_Ref);
/// The stack remains unchanged after the operation. /// The stack remains unchanged after the operation.
bool py_call(py_Ref f, int argc, py_Ref argv) PY_RAISE; bool py_call(py_Ref f, int argc, py_Ref argv) PY_RAISE;
#if PK_DEBUG
/// Call a py_CFunction in a safe way.
/// This function does extra checks to help you debug `py_CFunction`.
bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) PY_RAISE;
#else
#define py_callcfunc(f, argc, argv) f(argc, argv)
#endif
/// Python equivalent to `str(val)`. /// Python equivalent to `str(val)`.
bool py_str(py_Ref val) PY_RAISE; bool py_str(py_Ref val) PY_RAISE;
/// Python equivalent to `repr(val)`. /// Python equivalent to `repr(val)`.

View File

@ -269,7 +269,7 @@ FrameResult VM__run_top_frame(VM* self) {
py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__); py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__);
if(magic) { if(magic) {
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
if(!magic->_cfunc(2, SECOND())) goto __ERROR; if(!py_callcfunc(magic->_cfunc, 2, SECOND())) goto __ERROR;
POP(); POP();
} else { } else {
INSERT_THIRD(); // [?, a, b] INSERT_THIRD(); // [?, a, b]
@ -322,7 +322,7 @@ FrameResult VM__run_top_frame(VM* self) {
if(magic) { if(magic) {
PUSH(THIRD()); // [val, a, b, val] PUSH(THIRD()); // [val, a, b, val]
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
if(!magic->_cfunc(3, THIRD())) goto __ERROR; if(!py_callcfunc(magic->_cfunc, 3, THIRD())) goto __ERROR;
STACK_SHRINK(4); STACK_SHRINK(4);
} else { } else {
*FOURTH() = *magic; // [__selitem__, a, b, val] *FOURTH() = *magic; // [__selitem__, a, b, val]
@ -389,7 +389,7 @@ FrameResult VM__run_top_frame(VM* self) {
py_Ref magic = py_tpfindmagic(SECOND()->type, __delitem__); py_Ref magic = py_tpfindmagic(SECOND()->type, __delitem__);
if(magic) { if(magic) {
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
if(!magic->_cfunc(2, SECOND())) goto __ERROR; if(!py_callcfunc(magic->_cfunc, 2, SECOND())) goto __ERROR;
STACK_SHRINK(2); STACK_SHRINK(2);
} else { } else {
INSERT_THIRD(); // [?, a, b] INSERT_THIRD(); // [?, a, b]
@ -533,7 +533,7 @@ FrameResult VM__run_top_frame(VM* self) {
py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__); py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__);
if(magic) { if(magic) {
if(magic->type == tp_nativefunc) { if(magic->type == tp_nativefunc) {
if(!magic->_cfunc(2, SECOND())) goto __ERROR; if(!py_callcfunc(magic->_cfunc, 2, SECOND())) goto __ERROR;
STACK_SHRINK(2); STACK_SHRINK(2);
} else { } else {
INSERT_THIRD(); // [?, b, a] INSERT_THIRD(); // [?, b, a]

View File

@ -477,7 +477,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
} }
if(p0->type == tp_nativefunc) { if(p0->type == tp_nativefunc) {
bool ok = p0->_cfunc(p1 - argv, argv); bool ok = py_callcfunc(p0->_cfunc, p1 - argv, argv);
self->stack.sp = p0; self->stack.sp = p0;
return ok ? RES_RETURN : RES_ERROR; return ok ? RES_RETURN : RES_ERROR;
} }
@ -657,6 +657,6 @@ bool pk_wrapper__self(int argc, py_Ref argv) {
return true; return true;
} }
bool pk_wrapper__NotImplementedError(int argc, py_Ref argv){ bool pk_wrapper__NotImplementedError(int argc, py_Ref argv) {
return py_exception(tp_NotImplementedError, ""); return py_exception(tp_NotImplementedError, "");
} }

View File

@ -32,6 +32,7 @@ static bool os_chdir(int argc, py_Ref argv) {
const char* path = py_tostr(py_arg(0)); const char* path = py_tostr(py_arg(0));
int code = platform_chdir(path); int code = platform_chdir(path);
if(code != 0) return py_exception(tp_OSError, "chdir() failed: %d", code); if(code != 0) return py_exception(tp_OSError, "chdir() failed: %d", code);
py_newnone(py_retval());
return true; return true;
} }

View File

@ -105,7 +105,7 @@ bool py_exec(const char* source, const char* filename, enum py_CompileMode mode,
bool py_call(py_Ref f, int argc, py_Ref argv) { bool py_call(py_Ref f, int argc, py_Ref argv) {
if(f->type == tp_nativefunc) { if(f->type == tp_nativefunc) {
return f->_cfunc(argc, argv); return py_callcfunc(f->_cfunc, argc, argv);
} else { } else {
py_push(f); py_push(f);
py_pushnil(); py_pushnil();
@ -115,6 +115,16 @@ bool py_call(py_Ref f, int argc, py_Ref argv) {
} }
} }
bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) {
py_StackRef p0 = py_peek(0);
py_newnil(py_retval());
bool ok = f(argc, argv);
if(!ok) return false;
if(py_peek(0) != p0) c11__abort("py_CFunction must not change the stack!");
if(py_isnil(py_retval())) c11__abort("py_CFunction must set the return value!");
return true;
}
bool py_vectorcall(uint16_t argc, uint16_t kwargc) { bool py_vectorcall(uint16_t argc, uint16_t kwargc) {
VM* vm = pk_current_vm; VM* vm = pk_current_vm;
return VM__vectorcall(vm, argc, kwargc, false) != RES_ERROR; return VM__vectorcall(vm, argc, kwargc, false) != RES_ERROR;

View File

@ -319,6 +319,7 @@ static bool builtins_setattr(int argc, py_Ref argv) {
PY_CHECK_ARGC(3); PY_CHECK_ARGC(3);
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1))); py_Name name = py_namev(py_tosv(py_arg(1)));
py_newnone(py_retval());
return py_setattr(py_arg(0), name, py_arg(2)); return py_setattr(py_arg(0), name, py_arg(2));
} }
@ -344,6 +345,7 @@ static bool builtins_delattr(int argc, py_Ref argv) {
PY_CHECK_ARGC(2); PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str); PY_CHECK_ARG_TYPE(1, tp_str);
py_Name name = py_namev(py_tosv(py_arg(1))); py_Name name = py_namev(py_tosv(py_arg(1)));
py_newnone(py_retval());
return py_delattr(py_arg(0), name); return py_delattr(py_arg(0), name);
} }

View File

@ -211,6 +211,7 @@ static bool dict__new__(int argc, py_Ref argv) {
} }
static bool dict__init__(int argc, py_Ref argv) { static bool dict__init__(int argc, py_Ref argv) {
py_newnone(py_retval());
if(argc > 2) return TypeError("dict.__init__() takes at most 2 arguments (%d given)", argc); if(argc > 2) return TypeError("dict.__init__() takes at most 2 arguments (%d given)", argc);
if(argc == 1) return true; if(argc == 1) return true;
assert(argc == 2); assert(argc == 2);
@ -324,6 +325,7 @@ static bool dict__eq__(int argc, py_Ref argv) {
return true; return true;
} }
} }
py_newbool(py_retval(), true);
return true; return true;
} }
@ -340,6 +342,7 @@ static bool dict_clear(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
Dict* self = py_touserdata(argv); Dict* self = py_touserdata(argv);
Dict__clear(self); Dict__clear(self);
py_newnone(py_retval());
return true; return true;
} }
@ -366,6 +369,7 @@ static bool dict_update(int argc, py_Ref argv) {
if(py_isnil(&entry->key)) continue; if(py_isnil(&entry->key)) continue;
if(!Dict__set(self, &entry->key, &entry->val)) return false; if(!Dict__set(self, &entry->key, &entry->val)) return false;
} }
py_newnone(py_retval());
return true; return true;
} }

View File

@ -60,7 +60,8 @@ static bool _py_BaseException__new__(int argc, py_Ref argv) {
} }
static bool _py_BaseException__init__(int argc, py_Ref argv) { static bool _py_BaseException__init__(int argc, py_Ref argv) {
if(argc == 1 + 0) { return true; } py_newnone(py_retval());
if(argc == 1 + 0) return true;
if(argc == 1 + 1) { if(argc == 1 + 1) {
py_setslot(py_arg(0), 0, py_arg(1)); py_setslot(py_arg(0), 0, py_arg(1));
return true; return true;
@ -138,7 +139,7 @@ void py_printexc() {
free(msg); free(msg);
} }
static void c11_sbuf__write_exc(c11_sbuf* self, py_Ref exc){ static void c11_sbuf__write_exc(c11_sbuf* self, py_Ref exc) {
if(true) { c11_sbuf__write_cstr(self, "Traceback (most recent call last):\n"); } if(true) { c11_sbuf__write_cstr(self, "Traceback (most recent call last):\n"); }
BaseException* ud = py_touserdata(exc); BaseException* ud = py_touserdata(exc);
@ -174,7 +175,9 @@ char* py_formatexc() {
c11_sbuf__write_exc(&ss, &vm->curr_exception); c11_sbuf__write_exc(&ss, &vm->curr_exception);
} else { } else {
c11_sbuf__write_exc(&ss, inner); c11_sbuf__write_exc(&ss, inner);
c11_sbuf__write_cstr(&ss, "\n\nDuring handling of the above exception, another exception occurred:\n\n"); c11_sbuf__write_cstr(
&ss,
"\n\nDuring handling of the above exception, another exception occurred:\n\n");
c11_sbuf__write_exc(&ss, &vm->curr_exception); c11_sbuf__write_exc(&ss, &vm->curr_exception);
} }
@ -207,7 +210,7 @@ bool py_exception(py_Type type, const char* fmt, ...) {
bool py_raise(py_Ref exc) { bool py_raise(py_Ref exc) {
assert(py_isinstance(exc, tp_BaseException)); assert(py_isinstance(exc, tp_BaseException));
VM* vm = pk_current_vm; VM* vm = pk_current_vm;
if(!py_isnil(&vm->curr_exception)){ if(!py_isnil(&vm->curr_exception)) {
// inner exception // inner exception
py_setslot(exc, 1, &vm->curr_exception); py_setslot(exc, 1, &vm->curr_exception);
} }

View File

@ -167,6 +167,7 @@ static bool list__setitem__(int argc, py_Ref argv) {
int index = py_toint(py_arg(1)); int index = py_toint(py_arg(1));
if(!pk__normalize_index(&index, self->count)) return false; if(!pk__normalize_index(&index, self->count)) return false;
c11__setitem(py_TValue, self, index, *py_arg(2)); c11__setitem(py_TValue, self, index, *py_arg(2));
py_newnone(py_retval());
return true; return true;
} }

View File

@ -101,7 +101,7 @@ py_Name
return py_name(ud->decl->code.name->data); return py_name(ud->decl->code.name->data);
} }
void py_newboundmethod(py_Ref out, py_Ref self, py_Ref func){ void py_newboundmethod(py_Ref out, py_Ref self, py_Ref func) {
py_newobject(out, tp_boundmethod, 2, 0); py_newobject(out, tp_boundmethod, 2, 0);
py_setslot(out, 0, self); py_setslot(out, 0, self);
py_setslot(out, 1, func); py_setslot(out, 1, func);