blueloveTH 1 год назад
Родитель
Сommit
8ef573a800
10 измененных файлов с 40 добавлено и 22 удалено
  1. 6 2
      docs/2_0_0.md
  2. 1 1
      docs/cheatsheet.md
  3. 1 1
      docs/quick-start/exec.md
  4. 13 0
      include/pocketpy/error.h
  5. 5 5
      src/ceval.cpp
  6. 3 3
      src/compiler.cpp
  7. 4 4
      src/modules.cpp
  8. 3 3
      src/pocketpy.cpp
  9. 1 1
      src/pocketpy_c.cpp
  10. 3 2
      src/vm.cpp

+ 6 - 2
docs/1_5_0.md → docs/2_0_0.md

@@ -1,6 +1,6 @@
 ---
 icon: log
-title: 'Upgrade to v1.5.0'
+title: 'Upgrade to v2.0.0'
 order: 25
 ---
 
@@ -207,7 +207,7 @@ Enabling the profiler has a performance overhead. Only enable it when you need i
 + `vm->is_non_tagged_type` was removed. Use `vm->is_type` instead.
 + `vm->check_non_tagged_type` was removed. Use `vm->check_type` instead.
 
-## Python Stringify functions
+## Python stringify functions
 
 The following functions now return `Str` object instead of `PyVar`:
 
@@ -216,3 +216,7 @@ The following functions now return `Str` object instead of `PyVar`:
 + `vm->py_json`
 
 Also, `vm->bind__str__` and `vm->bind__repr__` were changed to return `Str` object.
+
+## Catching exceptions
+
+Now you need to catch `TopLevelException` instead of `Exception`.

+ 1 - 1
docs/cheatsheet.md

@@ -49,7 +49,7 @@ Execute a compiled code object
 ```cpp
 try{
     vm->_exec(co);    // may throw
-}catch(Exception& e){
+}catch(TopLevelException e){
     std::cerr << e.summary() << std::endl;
 }
 ```

+ 1 - 1
docs/quick-start/exec.md

@@ -52,7 +52,7 @@ These two methods are provided for this purpose:
 try{
     CodeObject_ code = vm->compile("a[0]", "main.py", EXEC_MODE, false);
     vm->_exec(code, vm->_main);
-}catch(Exception& e){
+}catch(TopLevelException e){
     // use e.summary() to get a summary of the exception
     std::cerr << e.summary() << std::endl;
 }

+ 13 - 0
include/pocketpy/error.h

@@ -88,4 +88,17 @@ struct Exception {
     Str summary() const;
 };
 
+struct TopLevelException: std::exception{
+    Exception* ptr;
+    TopLevelException(Exception* ptr): ptr(ptr) {}
+
+    PyObject* self() const { return ptr->self(); }
+    Str summary() const { return ptr->summary(); }
+
+    const char* what() const noexcept override {
+        static Str cached_summary(summary());
+        return cached_summary.c_str();
+    }
+};
+
 }   // namespace pkpy

+ 5 - 5
src/ceval.cpp

@@ -1,5 +1,4 @@
 #include "pocketpy/ceval.h"
-#include "pocketpy/codeobject.h"
 
 namespace pkpy{
 
@@ -1052,15 +1051,16 @@ __NEXT_STEP:
         }catch(InternalException internal){
             __internal_exception = internal;
             if(internal.type == InternalExceptionType::Unhandled){
-                PyVar e_obj = POPX();
-                Exception& _e = PK_OBJ_GET(Exception, e_obj);
+                __last_exception = POPX().get();
+                Exception& _e = __last_exception->as<Exception>();
                 bool is_base_frame_to_be_popped = frame == base_frame;
                 __pop_frame();
                 if(callstack.empty()){
-                    throw std::move(_e);    // propagate to the top level
+                    // propagate to the top level
+                    throw TopLevelException(&_e);
                 }
                 frame = &callstack.top();
-                PUSH(e_obj);
+                PUSH(__last_exception);
                 if(is_base_frame_to_be_popped){
                     throw InternalException(InternalExceptionType::ToBeRaised);
                 }

+ 3 - 3
src/compiler.cpp

@@ -1376,10 +1376,10 @@ __EAT_DOTS_END:
 
     // TODO: refactor this
     void Lexer::throw_err(StrName type, Str msg, int lineno, const char* cursor){
-        PyVar e_obj = vm->call(vm->builtins->attr(type), VAR(msg));
-        Exception& e = PK_OBJ_GET(Exception, e_obj);
+        vm->__last_exception = vm->call(vm->builtins->attr(type), VAR(msg)).get();
+        Exception& e = vm->__last_exception->as<Exception>();
         e.st_push(src, lineno, cursor, "");
-        throw std::move(e);
+        throw TopLevelException(&e);
     }
 
     std::string_view TokenDeserializer::read_string(char c){

+ 4 - 4
src/modules.cpp

@@ -198,15 +198,15 @@ void add_module_math(VM* vm){
 void add_module_traceback(VM* vm){
     PyObject* mod = vm->new_module("traceback");
     vm->bind_func(mod, "print_exc", 0, [](VM* vm, ArgsView args) {
-        if(vm->__last_exception==nullptr) vm->ValueError("no exception");
-        Exception& e = _CAST(Exception&, vm->__last_exception);
+        if(vm->__last_exception == nullptr) vm->ValueError("no exception");
+        Exception& e = vm->__last_exception->as<Exception>();
         vm->stdout_write(e.summary());
         return vm->None;
     });
 
     vm->bind_func(mod, "format_exc", 0, [](VM* vm, ArgsView args) {
-        if(vm->__last_exception==nullptr) vm->ValueError("no exception");
-        Exception& e = _CAST(Exception&, vm->__last_exception);
+        if(vm->__last_exception == nullptr) vm->ValueError("no exception");
+        Exception& e = vm->__last_exception->as<Exception>();
         return VAR(e.summary());
     });
 }

+ 3 - 3
src/pocketpy.cpp

@@ -1649,7 +1649,7 @@ void VM::__post_init_builtin_types(){
         this->_exec(code, this->builtins);
         code = compile(kPythonLibs__set, "<set>", EXEC_MODE);
         this->_exec(code, this->builtins);
-    }catch(const Exception& e){
+    }catch(TopLevelException e){
         std::cerr << e.summary() << std::endl;
         std::cerr << "failed to load builtins module!!" << std::endl;
         exit(1);
@@ -1679,7 +1679,7 @@ CodeObject_ VM::compile(std::string_view source, const Str& filename, CompileMod
     Compiler compiler(this, source, filename, mode, unknown_global_scope);
     try{
         return compiler.compile();
-    }catch(const Exception& e){
+    }catch(TopLevelException e){
         _error(e.self());
         return nullptr;
     }
@@ -1689,7 +1689,7 @@ Str VM::precompile(std::string_view source, const Str& filename, CompileMode mod
     Compiler compiler(this, source, filename, mode, false);
     try{
         return compiler.precompile();
-    }catch(const Exception& e){
+    }catch(TopLevelException e){
         _error(e.self());
         return nullptr;
     }

+ 1 - 1
src/pocketpy_c.cpp

@@ -44,7 +44,7 @@ static PyVar stack_item(VM* vm, int index){
 
 #define PK_PROTECTED(__B) \
     try{ __B }  \
-    catch(const Exception& e ) { \
+    catch(TopLevelException e) { \
         vm->__c.error = e.self(); \
         return false; \
     } catch(const std::exception& re){ \

+ 3 - 2
src/vm.cpp

@@ -1383,7 +1383,7 @@ PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Native
     try{
         // fn(a, b, *c, d=1) -> None
         co = compile(_S("def ", sig, " : pass"), "<bind>", EXEC_MODE);
-    }catch(const Exception&){
+    }catch(TopLevelException){
         throw std::runtime_error("invalid signature: " + std::string(sig));
     }
     if(co->func_decls.size() != 1){
@@ -1442,7 +1442,8 @@ void VM::_error(PyVar e_obj){
     Exception& e = PK_OBJ_GET(Exception, e_obj);
     if(callstack.empty()){
         e.is_re = false;
-        throw std::move(e);
+        __last_exception = e_obj.get();
+        throw TopLevelException(&e);
     }
     PUSH(e_obj);
     __raise_exc();