diff --git a/include/pocketpy/common/utils.h b/include/pocketpy/common/utils.h index 1b42ddf7..301a3cbe 100644 --- a/include/pocketpy/common/utils.h +++ b/include/pocketpy/common/utils.h @@ -27,9 +27,10 @@ extern "C" { #define c11__unreachedable() __builtin_unreachable() #endif -#define PK_FATAL_ERROR(...) \ +#define c11__abort(...) \ do { \ fprintf(stderr, __VA_ARGS__); \ + putchar('\n'); \ abort(); \ } while(0) diff --git a/src/common/str.c b/src/common/str.c index db279e4e..1fafaf30 100644 --- a/src/common/str.c +++ b/src/common/str.c @@ -255,7 +255,7 @@ int c11__u8_header(unsigned char c, bool suppress) { if((c & 0b11111000) == 0b11110000) return 4; if((c & 0b11111100) == 0b11111000) return 5; if((c & 0b11111110) == 0b11111100) return 6; - if(!suppress) PK_FATAL_ERROR("invalid utf8 char\n"); + if(!suppress) c11__abort("invalid utf8 char"); return 0; } diff --git a/src/common/strname.c b/src/common/strname.c index 284e640d..42e52a1e 100644 --- a/src/common/strname.c +++ b/src/common/strname.c @@ -38,7 +38,7 @@ py_Name py_namev(c11_sv name) { uint16_t index = c11_smallmap_s2n__get(&_interned, name, 0); if(index != 0) return index; // generate new index - if(_interned.count > 65530) PK_FATAL_ERROR("py_Name index overflow\n"); + if(_interned.count > 65530) c11__abort("py_Name index overflow"); // NOTE: we must allocate the string in the heap so iterators are not invalidated char* p = malloc(name.size + 1); memcpy(p, name.data, name.size); diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index c033e8cc..55d5938f 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -1484,8 +1484,7 @@ static NameScope name_scope(Compiler* self) { } Error* SyntaxError(const char* fmt, ...) { - printf("%s\n", fmt); - abort(); + c11__abort("%s", fmt); return NULL; } diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 1197de3f..68ed30c9 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -859,8 +859,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { } case OP_EXCEPTION_MATCH: { if(!py_checktype(TOP(), tp_type)) goto __ERROR; - bool ok = py_isinstance(TOP(), py_totype(&self->curr_exception)); - POP(); + bool ok = py_isinstance(&self->curr_exception, py_totype(TOP())); py_newbool(TOP(), ok); DISPATCH(); } diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index e92407af..4d8d8952 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -176,13 +176,14 @@ void pk_VM__ctor(pk_VM* self) { "AttributeError", "ImportError", "AssertionError", - // "KeyError", + "KeyError", NULL, // sentinel }; const char** it = builtin_exceptions; while(*it){ py_Type type = pk_newtype(*it, tp_Exception, &self->builtins, NULL, false, true); py_setdict(&self->builtins, py_name(*it), py_tpobject(type)); + it++; } py_TValue tmp; @@ -379,7 +380,6 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo #if 0 // handle boundmethod, do a patch if(p0->type == tp_boundmethod) { - assert(false); assert(py_isnil(p0 + 1)); // self must be NULL // BoundMethod& bm = PK_OBJ_GET(BoundMethod, callable); // callable = bm.func; // get unbound method diff --git a/src/objects/codeobject.c b/src/objects/codeobject.c index d96142c9..8fd398e7 100644 --- a/src/objects/codeobject.c +++ b/src/objects/codeobject.c @@ -4,7 +4,7 @@ void Bytecode__set_signed_arg(Bytecode* self, int arg) { if(arg < INT16_MIN || arg > INT16_MAX) { - PK_FATAL_ERROR("set_signed_arg: %d is out of range", arg); + c11__abort("set_signed_arg: %d is out of range", arg); } self->arg = (int16_t)arg; } diff --git a/src/public/error.c b/src/public/error.c index c830a52f..a5b6bb80 100644 --- a/src/public/error.c +++ b/src/public/error.c @@ -1,3 +1,4 @@ +#include "pocketpy/common/utils.h" #include "pocketpy/objects/base.h" #include "pocketpy/pocketpy.h" #include "pocketpy/common/sstream.h" @@ -17,7 +18,7 @@ void py_printexc() { } else { const char* name = py_tpname(vm->curr_exception.type); bool ok = py_str(&vm->curr_exception); - if(!ok) abort(); + if(!ok) c11__abort("py_printexc(): failed to convert exception to string"); const char* message = py_tostr(py_retval()); vm->_stdout("%s: %s\n", name, message); } @@ -43,8 +44,11 @@ bool py_exception(const char* name, const char* fmt, ...) { py_Ref message = py_pushtmp(); py_newstrn(message, res->data, res->size); c11_string__delete(res); - bool ok = py_tpcall(tp_Exception, 1, message); - if(!ok) abort(); + + py_Ref exc_type = py_getdict(&pk_current_vm->builtins, py_name(name)); + if(exc_type == NULL) c11__abort("py_exception(): '%s' not found", name); + bool ok = py_call(exc_type, 1, message); + if(!ok) c11__abort("py_exception(): failed to create exception object"); py_pop(); return py_raise(py_retval()); diff --git a/src/public/modules.c b/src/public/modules.c index 3662f004..cc24429c 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -45,7 +45,7 @@ py_Ref py_newmodule(const char* name, const char* package) { // we do not allow override in order to avoid memory leak // it is because Module objects are not garbage collected bool exists = pk_NameDict__contains(&pk_current_vm->modules, py_name(name)); - if(exists) abort(); + if(exists) c11__abort("module '%s' already exists", name); pk_NameDict__set(&pk_current_vm->modules, py_name(name), *r0); py_shrink(2); diff --git a/src/public/values.c b/src/public/values.c index c9f35433..8b55b8ba 100644 --- a/src/public/values.c +++ b/src/public/values.c @@ -73,8 +73,8 @@ void py_bind(py_Ref obj, const char* sig, py_CFunction f) { CodeObject code; pk_SourceData_ source = pk_SourceData__rcnew(buffer, "", EXEC_MODE, false); Error* err = pk_compile(source, &code); - if(err) abort(); - if(code.func_decls.count != 1) abort(); + if(err) c11__abort("py_bind(): failed to compile signature '%s'", sig); + if(code.func_decls.count != 1) c11__abort("py_bind(): invalid signature '%s'", sig); FuncDecl_ decl = c11__getitem(FuncDecl_, &code.func_decls, 0); // construct the function Function* ud = py_newobject(&tmp, tp_function, 0, sizeof(Function));