blueloveTH 1 an în urmă
părinte
comite
45de08dd39

+ 3 - 1
include/pocketpy/interpreter/vm.h

@@ -51,7 +51,7 @@ typedef struct pk_VM {
     void (*_stderr)(const char*, ...);
 
     py_TValue last_retval;
-    bool has_error;
+    py_TValue last_exception;
     bool is_stopiteration;
 
     py_TValue reg[8];  // users' registers
@@ -114,6 +114,8 @@ py_Type pk_function__register();
 py_Type pk_nativefunc__register();
 py_Type pk_range__register();
 py_Type pk_range_iterator__register();
+py_Type pk_BaseException__register();
+py_Type pk_Exception__register();
 
 py_TValue pk_builtins__register();
 

+ 2 - 2
include/pocketpy/objects/error.h

@@ -13,12 +13,12 @@ extern "C" {
 //     pk_SourceData_ src;
 //     int lineno;
 //     const char* cursor;
-//     py_Str name;
+//     c11_string* name;
 // } pkpy_ExceptionFrame;
 
 // typedef struct pkpy_Exception {
 //     py_Name type;
-//     py_Str msg;
+//     c11_string* msg;
 //     bool is_re;
 
 //     int _ip_on_error;

+ 1 - 0
include/pocketpy/pocketpy.h

@@ -409,6 +409,7 @@ enum py_PredefinedTypes {
     tp_nativefunc,
     tp_bound_method,
     tp_super,  // 1 slot + py_Type
+    tp_base_exception,
     tp_exception,
     tp_bytes,
     tp_mappingproxy,

+ 1 - 2
src/interpreter/ceval.c

@@ -83,7 +83,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
     __NEXT_STEP:
         byte = *frame->ip;
 
-#if 0
+#if 1
         c11_sbuf buf;
         c11_sbuf__ctor(&buf);
         for(py_Ref p = self->stack.begin; p != SP(); p++) {
@@ -777,7 +777,6 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
         // 1. Exception can be handled inside the current frame
         // 2. Exception need to be propagated to the upper frame
         printf("error.op: %s, line: %d\n", pk_opname(byte.op), Frame__lineno(frame));
-        assert(false);
         return RES_ERROR;
     }
 

+ 4 - 2
src/interpreter/vm.c

@@ -71,7 +71,7 @@ void pk_VM__ctor(pk_VM* self) {
     self->_stderr = pk_default_stderr;
 
     self->last_retval = PY_NIL;
-    self->has_error = false;
+    self->last_exception = PY_NIL;
     self->is_stopiteration = false;
 
     self->__curr_class = PY_NIL;
@@ -112,7 +112,8 @@ void pk_VM__ctor(pk_VM* self) {
     validate(tp_bound_method, pk_VM__new_type(self, "bound_method", tp_object, NULL, false));
 
     validate(tp_super, pk_VM__new_type(self, "super", tp_object, NULL, false));
-    validate(tp_exception, pk_VM__new_type(self, "Exception", tp_object, NULL, true));
+    validate(tp_base_exception, pk_BaseException__register());
+    validate(tp_exception, pk_Exception__register());
     validate(tp_bytes, pk_bytes__register());
     validate(tp_mappingproxy, pk_VM__new_type(self, "mappingproxy", tp_object, NULL, false));
 
@@ -148,6 +149,7 @@ void pk_VM__ctor(pk_VM* self) {
                               tp_bytes,
                               tp_dict,
                               tp_property,
+                              tp_base_exception,
                               tp_exception,
                               tp_stop_iteration,
                               tp_syntax_error};

+ 0 - 0
src/error.c → src/objects/error.c


+ 20 - 13
src/public/error.c

@@ -4,24 +4,25 @@
 
 #include <stdarg.h>
 
-void py_printexc(){
+void py_printexc() {
     pk_VM* vm = pk_current_vm;
-    if(vm->has_error){
-        assert(vm->last_retval.type == tp_exception);
-    }else{
+    if(py_isnil(&vm->last_exception)) {
         vm->_stdout("NoneType: None\n");
+    } else {
+        const char* name = py_tpname(vm->last_exception.type);
+        bool ok = py_str(&vm->last_exception);
+        if(!ok) abort();
+        const char* message = py_tostr(py_retval());
+        vm->_stdout("%s: %s\n", name, message);
     }
 }
 
+void py_formatexc(char* out) {}
 
-void py_formatexc(char *out){
-
-}
-
-bool py_exception(const char* name, const char* fmt, ...){
+bool py_exception(const char* name, const char* fmt, ...) {
     pk_VM* vm = pk_current_vm;
-    assert(!vm->has_error);     // an error is already set
-    vm->has_error = true;
+    // an error is already set
+    assert(py_isnil(&vm->last_exception));
 
     c11_sbuf buf;
     c11_sbuf__ctor(&buf);
@@ -31,8 +32,14 @@ bool py_exception(const char* name, const char* fmt, ...){
     va_end(args);
 
     c11_string* res = c11_sbuf__submit(&buf);
-    // vm->last_retval = py_newexception(name, res->data);
-    vm->_stderr("%s: %s\n", name, res->data);
+    py_Ref message = py_pushtmp();
+    py_newstrn(message, res->data, res->size);
     c11_string__delete(res);
+    py_pop();
+
+    bool ok = py_tpcall(tp_exception, 1, message);
+    if(!ok) abort();
+    vm->last_exception = *py_retval();
+
     return false;
 }

+ 81 - 0
src/public/py_exception.c

@@ -0,0 +1,81 @@
+#include "pocketpy/pocketpy.h"
+
+#include "pocketpy/common/utils.h"
+#include "pocketpy/objects/object.h"
+#include "pocketpy/interpreter/vm.h"
+#include "pocketpy/common/sstream.h"
+
+typedef struct BaseExceptionFrame {
+    pk_SourceData_ src;
+    int lineno;
+    c11_string* name;
+} BaseExceptionFrame;
+
+typedef struct BaseException {
+    int ip_backup;
+    CodeObject* code_backup;
+    c11_vector /*T=BaseExceptionFrame*/ stacktrace;
+} BaseException;
+
+static bool _py_BaseException__new__(int argc, py_Ref argv) {
+    py_Type cls = py_totype(argv);
+    BaseException* ud = py_newobject(py_retval(), cls, 1, sizeof(BaseException));
+    ud->ip_backup = -1;
+    ud->code_backup = NULL;
+    return true;
+}
+
+static bool _py_BaseException__init__(int argc, py_Ref argv) {
+    if(argc == 1 + 0) { return true; }
+    if(argc == 1 + 1) {
+        py_setslot(py_arg(0), 0, py_arg(1));
+        return true;
+    }
+    return TypeError("__init__() takes at most 2 arguments but %d were given", argc);
+}
+
+static bool _py_BaseException__repr__(int argc, py_Ref argv) {
+    c11_sbuf ss;
+    c11_sbuf__ctor(&ss);
+    pk_sprintf(&ss, "%t(", argv->type);
+    py_Ref arg = py_getslot(argv, 0);
+    if(!py_isnil(arg)) {
+        if(!py_repr(arg)) return false;
+        c11_sbuf__write_sv(&ss, py_tosv(py_retval()));
+    }
+    c11_sbuf__write_char(&ss, ')');
+    c11_string* res = c11_sbuf__submit(&ss);
+    py_newstrn(py_retval(), res->data, res->size);
+    c11_string__delete(res);
+    return true;
+}
+
+static bool _py_BaseException__str__(int argc, py_Ref argv) {
+    c11_sbuf ss;
+    c11_sbuf__ctor(&ss);
+    py_Ref arg = py_getslot(argv, 0);
+    if(!py_isnil(arg)) {
+        if(!py_str(arg)) return false;
+        c11_sbuf__write_sv(&ss, py_tosv(py_retval()));
+    }
+    c11_string* res = c11_sbuf__submit(&ss);
+    py_newstrn(py_retval(), res->data, res->size);
+    c11_string__delete(res);
+    return true;
+}
+
+py_Type pk_BaseException__register() {
+    pk_VM* vm = pk_current_vm;
+    py_Type type = pk_VM__new_type(vm, "BaseException", tp_object, NULL, true);
+    py_bindmagic(type, __new__, _py_BaseException__new__);
+    py_bindmagic(type, __init__, _py_BaseException__init__);
+    py_bindmagic(type, __repr__, _py_BaseException__repr__);
+    py_bindmagic(type, __str__, _py_BaseException__str__);
+    return type;
+}
+
+py_Type pk_Exception__register() {
+    pk_VM* vm = pk_current_vm;
+    py_Type type = pk_VM__new_type(vm, "Exception", tp_base_exception, NULL, true);
+    return type;
+}

+ 0 - 4
tests/00_tmp.py

@@ -1,4 +0,0 @@
-def f(a, b):
-    return a+b
-
-assert f(1, 2) == 3