mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
...
... ...
This commit is contained in:
parent
acc8ab802f
commit
1614502741
12
docs/modules/traceback.md
Normal file
12
docs/modules/traceback.md
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
icon: package
|
||||
label: traceback
|
||||
---
|
||||
|
||||
### `trackback.print_exc() -> None`
|
||||
|
||||
Print the last exception and its traceback.
|
||||
|
||||
### `trackback.format_exc() -> str`
|
||||
|
||||
Return the last exception and its traceback as a string.
|
@ -103,4 +103,36 @@ For example, `vm->bind__add__` is preferred over `vm->bind_method<1>(type, "__ad
|
||||
|
||||
### Bind a property
|
||||
|
||||
You can use `vm->property(...)` to create a `property` object and assign it to an type object.
|
||||
a property is a python's `property` that attached to a type instance with a getter and an optional setter. It is a data descriptor. A property redirects attribute access to specific functions.
|
||||
|
||||
You can use `@property` to create python property or use `vm->property` to create native property.
|
||||
|
||||
```cpp
|
||||
struct Point {
|
||||
PY_CLASS(Point, test, Point);
|
||||
|
||||
int x;
|
||||
int y;
|
||||
|
||||
Point(int x, int y) : x(x), y(y) {}
|
||||
|
||||
static void _register(VM *vm, auto mod, auto type) {
|
||||
vm->bind_constructor<3>(type, [](VM *vm, auto args) {
|
||||
auto x = CAST(i64, args[1]);
|
||||
auto y = CAST(i64, args[2]);
|
||||
return VAR_T(Point, x, y);
|
||||
});
|
||||
|
||||
// getter and setter of property `x`
|
||||
type->attr().set("x", vm->property([](VM* vm, ArgsView args){
|
||||
Point& self = CAST(Point&, args[0]);
|
||||
return VAR(self.x);
|
||||
},
|
||||
[](VM* vm, ArgsView args){
|
||||
Point& self = CAST(Point&, args[0]);
|
||||
self.x = CAST(int, args[1]);
|
||||
return vm->None;
|
||||
}));
|
||||
}
|
||||
};
|
||||
```
|
@ -583,6 +583,7 @@ __NEXT_STEP:;
|
||||
_error(StrName(byte.arg), msg);
|
||||
} DISPATCH();
|
||||
TARGET(RE_RAISE) _raise(); DISPATCH();
|
||||
TARGET(POP_EXCEPTION) _last_exception = POPX(); DISPATCH();
|
||||
/*****************************************/
|
||||
TARGET(SETUP_DOCSTRING)
|
||||
TOP()->attr().set(__doc__, co_consts[byte.arg]);
|
||||
|
@ -624,7 +624,7 @@ __SUBSCR_END:
|
||||
}
|
||||
int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
||||
// pop the exception on match
|
||||
ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||
ctx()->emit(OP_POP_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
||||
compile_block_body();
|
||||
patches.push_back(ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE));
|
||||
ctx()->patch_jump(patch);
|
||||
|
@ -113,6 +113,7 @@ OPCODE(ASSERT)
|
||||
OPCODE(EXCEPTION_MATCH)
|
||||
OPCODE(RAISE)
|
||||
OPCODE(RE_RAISE)
|
||||
OPCODE(POP_EXCEPTION)
|
||||
/**************************/
|
||||
OPCODE(SETUP_DOCSTRING)
|
||||
OPCODE(FORMAT_STRING)
|
||||
|
@ -1155,6 +1155,22 @@ inline void add_module_math(VM* vm){
|
||||
});
|
||||
}
|
||||
|
||||
inline void add_module_traceback(VM* vm){
|
||||
PyObject* mod = vm->new_module("traceback");
|
||||
vm->bind_func<0>(mod, "print_exc", [](VM* vm, ArgsView args) {
|
||||
if(vm->_last_exception==nullptr) vm->ValueError("no exception");
|
||||
Exception& e = CAST(Exception&, vm->_last_exception);
|
||||
vm->_stdout(vm, e.summary());
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
vm->bind_func<0>(mod, "format_exc", [](VM* vm, ArgsView args) {
|
||||
if(vm->_last_exception==nullptr) vm->ValueError("no exception");
|
||||
Exception& e = CAST(Exception&, vm->_last_exception);
|
||||
return VAR(e.summary());
|
||||
});
|
||||
}
|
||||
|
||||
inline void add_module_dis(VM* vm){
|
||||
PyObject* mod = vm->new_module("dis");
|
||||
vm->bind_func<1>(mod, "dis", [](VM* vm, ArgsView args) {
|
||||
@ -1306,6 +1322,7 @@ inline void VM::post_init(){
|
||||
init_builtins(this);
|
||||
#if !DEBUG_NO_BUILTIN_MODULES
|
||||
add_module_sys(this);
|
||||
add_module_traceback(this);
|
||||
add_module_time(this);
|
||||
add_module_json(this);
|
||||
add_module_math(this);
|
||||
|
6
src/vm.h
6
src/vm.h
@ -123,6 +123,8 @@ public:
|
||||
PyObject* StopIteration;
|
||||
PyObject* _main; // __main__ module
|
||||
|
||||
PyObject* _last_exception;
|
||||
|
||||
PrintFunc _stdout;
|
||||
PrintFunc _stderr;
|
||||
|
||||
@ -142,6 +144,7 @@ public:
|
||||
_stderr = [](VM* vm, const Str& s) { std::cerr << s; };
|
||||
callstack.reserve(8);
|
||||
_main = nullptr;
|
||||
_last_exception = nullptr;
|
||||
init_builtin_types();
|
||||
}
|
||||
|
||||
@ -1448,7 +1451,8 @@ inline void ManagedHeap::mark() {
|
||||
for(PyObject* obj: _no_gc) OBJ_MARK(obj);
|
||||
for(auto& frame : vm->callstack.data()) frame._gc_mark();
|
||||
for(PyObject* obj: vm->s_data) OBJ_MARK(obj);
|
||||
if(_gc_marker_ex != nullptr) _gc_marker_ex(vm);
|
||||
if(_gc_marker_ex) _gc_marker_ex(vm);
|
||||
if(vm->_last_exception) OBJ_MARK(vm->_last_exception);
|
||||
}
|
||||
|
||||
inline Str obj_type_name(VM *vm, Type type){
|
||||
|
10
tests/80_traceback.py
Normal file
10
tests/80_traceback.py
Normal file
@ -0,0 +1,10 @@
|
||||
import traceback
|
||||
|
||||
try:
|
||||
a = {'123': 4}
|
||||
b = a[6]
|
||||
except KeyError:
|
||||
s = traceback.format_exc()
|
||||
|
||||
assert s == r'''Traceback (most recent call last):
|
||||
KeyError: 6'''
|
Loading…
x
Reference in New Issue
Block a user