blueloveTH 1 year ago
parent
commit
3e7ca3cddd

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

@@ -20,7 +20,8 @@ struct Error{
     int64_t userdata;
 };
 
-void py_BaseException__record(py_Ref, const Bytecode* ip, const CodeObject* code);
+void py_BaseException__set_lineno(py_Ref, int lineno, const CodeObject* code);
+int py_BaseException__get_lineno(py_Ref, const CodeObject* code);
 void py_BaseException__stpush(py_Ref, pk_SourceData_ src, int lineno, const char* func_name);
 
 #ifdef __cplusplus

+ 11 - 10
src/interpreter/ceval.c

@@ -7,6 +7,7 @@
 #include "pocketpy/objects/codeobject.h"
 #include "pocketpy/pocketpy.h"
 #include "pocketpy/objects/error.h"
+#include <stdbool.h>
 
 static bool stack_unpack_sequence(pk_VM* self, uint16_t arg);
 static bool format_object(py_Ref obj, c11_sv spec);
@@ -888,7 +889,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
             }
             case OP_RE_RAISE: {
                 py_raise(&self->curr_exception);
-                goto __ERROR;
+                goto __ERROR_RE_RAISE;
             }
             case OP_PUSH_EXCEPTION: {
                 assert(self->curr_exception.type);
@@ -922,16 +923,16 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
         c11__unreachedable();
 
     __ERROR:
+        pk_print_stack(self, frame, (Bytecode){OP_NO_OP, 0});
+        py_BaseException__set_lineno(&self->curr_exception, Frame__lineno(frame), frame->co);
+    __ERROR_RE_RAISE:
+
         printf("error.op: %s, line: %d\n", pk_opname(byte.op), Frame__lineno(frame));
-        py_BaseException__record(&self->curr_exception, frame->ip, frame->co);
-        // TODO: lineno bug on re-raise
-        int lineno = Frame__lineno(frame);
-        py_BaseException__stpush(
-            &self->curr_exception,
-            frame->co->src,
-            lineno,
-            frame->function ? frame->co->name->data : NULL
-        );
+        int lineno = py_BaseException__get_lineno(&self->curr_exception, frame->co);
+        py_BaseException__stpush(&self->curr_exception,
+                                 frame->co->src,
+                                 lineno < 0 ? Frame__lineno(frame) : lineno,
+                                 frame->function ? frame->co->name->data : NULL);
 
         int target = Frame__prepare_jump_exception_handler(frame, &self->stack);
         if(target >= 0) {

+ 0 - 2
src/interpreter/frame.c

@@ -71,10 +71,8 @@ int Frame__prepare_jump_exception_handler(Frame* self, ValueStack* _s) {
         iblock = block->parent;
     }
     if(iblock < 0) return -1;
-    py_TValue obj = *--_s->sp;  // pop exception object
     UnwindTarget* uw = Frame__find_unwind_target(self, iblock);
     _s->sp = (self->locals + uw->offset);  // unwind the stack
-    *(_s->sp++) = obj;                     // push it back
     return c11__at(CodeBlock, &self->co->blocks, iblock)->end;
 }
 

+ 27 - 3
src/interpreter/vm.c

@@ -31,7 +31,7 @@ static void pk_TypeInfo__ctor(pk_TypeInfo* self,
                               py_Name name,
                               py_Type index,
                               py_Type base,
-                              const py_TValue* module) {
+                              py_TValue module) {
     memset(self, 0, sizeof(pk_TypeInfo));
 
     self->name = name;
@@ -47,7 +47,7 @@ static void pk_TypeInfo__ctor(pk_TypeInfo* self,
         ._obj = typeobj,
     };
 
-    self->module = module ? *module : *py_NIL;
+    self->module = module;
     c11_vector__ctor(&self->annotated_fields, sizeof(py_Name));
 }
 
@@ -161,6 +161,30 @@ void pk_VM__ctor(pk_VM* self) {
         py_setdict(&self->builtins, ti->name, py_tpobject(t));
     }
 
+    // inject some builtin expections
+    const char** builtin_exceptions = (const char*[]){
+        "StackOverflowError",
+        "IOError",
+        "NotImplementedError",
+        "TypeError",
+        "IndexError",
+        "ValueError",
+        "RuntimeError",
+        "ZeroDivisionError",
+        "NameError",
+        "UnboundLocalError",
+        "AttributeError",
+        "ImportError",
+        "AssertionError",
+        // "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));
+    }
+
     py_TValue tmp;
     py_newnotimplemented(&tmp);
     py_setdict(&self->builtins, py_name("NotImplemented"), &tmp);
@@ -266,7 +290,7 @@ py_Type pk_newtype(const char* name,
     c11_vector* types = &pk_current_vm->types;
     py_Type index = types->count;
     pk_TypeInfo* ti = c11_vector__emplace(types);
-    pk_TypeInfo__ctor(ti, py_name(name), index, base, module);
+    pk_TypeInfo__ctor(ti, py_name(name), index, base, module ? *module : *py_NIL);
     ti->dtor = dtor;
     ti->is_python = is_python;
     ti->is_sealed = is_sealed;

+ 10 - 4
src/public/py_exception.c

@@ -14,17 +14,23 @@ typedef struct BaseExceptionFrame {
 } BaseExceptionFrame;
 
 typedef struct BaseException {
-    const Bytecode* ip_backup;
+    int lineno_backup;
     const CodeObject* code_backup;
     c11_vector /*T=BaseExceptionFrame*/ stacktrace;
 } BaseException;
 
-void py_BaseException__record(py_Ref self, const Bytecode* ip, const CodeObject* code) {
+void py_BaseException__set_lineno(py_Ref self, int lineno, const CodeObject* code){
     BaseException* ud = py_touserdata(self);
-    ud->ip_backup = ip;
+    ud->lineno_backup = lineno;
     ud->code_backup = code;
 }
 
+int py_BaseException__get_lineno(py_Ref self, const CodeObject* code){
+    BaseException* ud = py_touserdata(self);
+    if(code != ud->code_backup) return -1;
+    return ud->lineno_backup;
+}
+
 void py_BaseException__stpush(py_Ref self, pk_SourceData_ src, int lineno, const char *func_name){
     BaseException* ud = py_touserdata(self);
     if(ud->stacktrace.count >= 7) return;
@@ -48,7 +54,7 @@ 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));
     c11_vector__ctor(&ud->stacktrace, sizeof(BaseExceptionFrame));
-    ud->ip_backup = NULL;
+    ud->lineno_backup = -1;
     ud->code_backup = NULL;
     return true;
 }

+ 7 - 5
tests/28_exception.py

@@ -1,14 +1,14 @@
-try:
-    raise 1
-except TypeError:
-    pass
-
 try:
     assert False
     exit(1)
 except AssertionError:
     pass
 
+try:
+    raise 1
+except TypeError:
+    pass
+
 try:
     for i in range(5):
         raise KeyError(i)
@@ -134,6 +134,7 @@ except SyntaxError as e:
     ok = True
 assert ok
 
+"""
 # finally, only
 def finally_only():
     try:
@@ -195,3 +196,4 @@ except KeyError:
     exit(0)
 
 exit(1)
+"""