From 4829568c87e00540c08940f4ad53b51f01039aaf Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Thu, 8 Aug 2024 14:08:17 +0800 Subject: [PATCH] ... --- include/pocketpy/common/config.h | 6 ++++++ include/pocketpy/pocketpy.h | 10 +++++++++- src/interpreter/ceval.c | 8 ++++---- src/interpreter/vm.c | 4 ++-- src/modules/os.c | 1 + src/public/internal.c | 12 +++++++++++- src/public/modules.c | 2 ++ src/public/py_dict.c | 4 ++++ src/public/py_exception.c | 11 +++++++---- src/public/py_list.c | 1 + src/public/values.c | 2 +- 11 files changed, 48 insertions(+), 13 deletions(-) diff --git a/include/pocketpy/common/config.h b/include/pocketpy/common/config.h index 10ac5a8d..f67c3995 100644 --- a/include/pocketpy/common/config.h +++ b/include/pocketpy/common/config.h @@ -50,3 +50,9 @@ #else #define PK_PLATFORM_SEP '/' #endif + +#ifdef NDEBUG + #define PK_DEBUG 0 +#else + #define PK_DEBUG 1 +#endif \ No newline at end of file diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 93ee560c..ac1996e0 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -304,7 +304,7 @@ bool py_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE; /// Python equivalent to `del self[key]`. 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 stack remains unchanged after the operation. 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. 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)`. bool py_str(py_Ref val) PY_RAISE; /// Python equivalent to `repr(val)`. diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 456ceb6b..775d773b 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -269,7 +269,7 @@ FrameResult VM__run_top_frame(VM* self) { py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__); if(magic) { if(magic->type == tp_nativefunc) { - if(!magic->_cfunc(2, SECOND())) goto __ERROR; + if(!py_callcfunc(magic->_cfunc, 2, SECOND())) goto __ERROR; POP(); } else { INSERT_THIRD(); // [?, a, b] @@ -322,7 +322,7 @@ FrameResult VM__run_top_frame(VM* self) { if(magic) { PUSH(THIRD()); // [val, a, b, val] if(magic->type == tp_nativefunc) { - if(!magic->_cfunc(3, THIRD())) goto __ERROR; + if(!py_callcfunc(magic->_cfunc, 3, THIRD())) goto __ERROR; STACK_SHRINK(4); } else { *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__); if(magic) { if(magic->type == tp_nativefunc) { - if(!magic->_cfunc(2, SECOND())) goto __ERROR; + if(!py_callcfunc(magic->_cfunc, 2, SECOND())) goto __ERROR; STACK_SHRINK(2); } else { INSERT_THIRD(); // [?, a, b] @@ -533,7 +533,7 @@ FrameResult VM__run_top_frame(VM* self) { py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__); if(magic) { if(magic->type == tp_nativefunc) { - if(!magic->_cfunc(2, SECOND())) goto __ERROR; + if(!py_callcfunc(magic->_cfunc, 2, SECOND())) goto __ERROR; STACK_SHRINK(2); } else { INSERT_THIRD(); // [?, b, a] diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 117fd7ce..8df205f1 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -477,7 +477,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall } 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; return ok ? RES_RETURN : RES_ERROR; } @@ -657,6 +657,6 @@ bool pk_wrapper__self(int argc, py_Ref argv) { 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, ""); } \ No newline at end of file diff --git a/src/modules/os.c b/src/modules/os.c index f8dff7e0..d3338b3a 100644 --- a/src/modules/os.c +++ b/src/modules/os.c @@ -32,6 +32,7 @@ static bool os_chdir(int argc, py_Ref argv) { const char* path = py_tostr(py_arg(0)); int code = platform_chdir(path); if(code != 0) return py_exception(tp_OSError, "chdir() failed: %d", code); + py_newnone(py_retval()); return true; } diff --git a/src/public/internal.c b/src/public/internal.c index f4c91bbc..0b0c57fa 100644 --- a/src/public/internal.c +++ b/src/public/internal.c @@ -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) { if(f->type == tp_nativefunc) { - return f->_cfunc(argc, argv); + return py_callcfunc(f->_cfunc, argc, argv); } else { py_push(f); 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) { VM* vm = pk_current_vm; return VM__vectorcall(vm, argc, kwargc, false) != RES_ERROR; diff --git a/src/public/modules.c b/src/public/modules.c index 11bb0da5..1f64a109 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -319,6 +319,7 @@ static bool builtins_setattr(int argc, py_Ref argv) { PY_CHECK_ARGC(3); PY_CHECK_ARG_TYPE(1, tp_str); py_Name name = py_namev(py_tosv(py_arg(1))); + py_newnone(py_retval()); 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_ARG_TYPE(1, tp_str); py_Name name = py_namev(py_tosv(py_arg(1))); + py_newnone(py_retval()); return py_delattr(py_arg(0), name); } diff --git a/src/public/py_dict.c b/src/public/py_dict.c index bd4ebf0b..6888eedd 100644 --- a/src/public/py_dict.c +++ b/src/public/py_dict.c @@ -211,6 +211,7 @@ static bool dict__new__(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 == 1) return true; assert(argc == 2); @@ -324,6 +325,7 @@ static bool dict__eq__(int argc, py_Ref argv) { return true; } } + py_newbool(py_retval(), true); return true; } @@ -340,6 +342,7 @@ static bool dict_clear(int argc, py_Ref argv) { PY_CHECK_ARGC(1); Dict* self = py_touserdata(argv); Dict__clear(self); + py_newnone(py_retval()); return true; } @@ -366,6 +369,7 @@ static bool dict_update(int argc, py_Ref argv) { if(py_isnil(&entry->key)) continue; if(!Dict__set(self, &entry->key, &entry->val)) return false; } + py_newnone(py_retval()); return true; } diff --git a/src/public/py_exception.c b/src/public/py_exception.c index 6bd1198b..4ccdeee1 100644 --- a/src/public/py_exception.c +++ b/src/public/py_exception.c @@ -60,7 +60,8 @@ static bool _py_BaseException__new__(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) { py_setslot(py_arg(0), 0, py_arg(1)); return true; @@ -138,7 +139,7 @@ void py_printexc() { 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"); } BaseException* ud = py_touserdata(exc); @@ -174,7 +175,9 @@ char* py_formatexc() { c11_sbuf__write_exc(&ss, &vm->curr_exception); } else { 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); } @@ -207,7 +210,7 @@ bool py_exception(py_Type type, const char* fmt, ...) { bool py_raise(py_Ref exc) { assert(py_isinstance(exc, tp_BaseException)); VM* vm = pk_current_vm; - if(!py_isnil(&vm->curr_exception)){ + if(!py_isnil(&vm->curr_exception)) { // inner exception py_setslot(exc, 1, &vm->curr_exception); } diff --git a/src/public/py_list.c b/src/public/py_list.c index 88805466..26e75d3d 100644 --- a/src/public/py_list.c +++ b/src/public/py_list.c @@ -167,6 +167,7 @@ static bool list__setitem__(int argc, py_Ref argv) { int index = py_toint(py_arg(1)); if(!pk__normalize_index(&index, self->count)) return false; c11__setitem(py_TValue, self, index, *py_arg(2)); + py_newnone(py_retval()); return true; } diff --git a/src/public/values.c b/src/public/values.c index a5dc45f4..9a57365b 100644 --- a/src/public/values.c +++ b/src/public/values.c @@ -101,7 +101,7 @@ py_Name 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_setslot(out, 0, self); py_setslot(out, 1, func);