mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40: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
|
### 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);
|
_error(StrName(byte.arg), msg);
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(RE_RAISE) _raise(); DISPATCH();
|
TARGET(RE_RAISE) _raise(); DISPATCH();
|
||||||
|
TARGET(POP_EXCEPTION) _last_exception = POPX(); DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
TARGET(SETUP_DOCSTRING)
|
TARGET(SETUP_DOCSTRING)
|
||||||
TOP()->attr().set(__doc__, co_consts[byte.arg]);
|
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);
|
int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
||||||
// pop the exception on match
|
// 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();
|
compile_block_body();
|
||||||
patches.push_back(ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE));
|
patches.push_back(ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE));
|
||||||
ctx()->patch_jump(patch);
|
ctx()->patch_jump(patch);
|
||||||
|
@ -113,6 +113,7 @@ OPCODE(ASSERT)
|
|||||||
OPCODE(EXCEPTION_MATCH)
|
OPCODE(EXCEPTION_MATCH)
|
||||||
OPCODE(RAISE)
|
OPCODE(RAISE)
|
||||||
OPCODE(RE_RAISE)
|
OPCODE(RE_RAISE)
|
||||||
|
OPCODE(POP_EXCEPTION)
|
||||||
/**************************/
|
/**************************/
|
||||||
OPCODE(SETUP_DOCSTRING)
|
OPCODE(SETUP_DOCSTRING)
|
||||||
OPCODE(FORMAT_STRING)
|
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){
|
inline void add_module_dis(VM* vm){
|
||||||
PyObject* mod = vm->new_module("dis");
|
PyObject* mod = vm->new_module("dis");
|
||||||
vm->bind_func<1>(mod, "dis", [](VM* vm, ArgsView args) {
|
vm->bind_func<1>(mod, "dis", [](VM* vm, ArgsView args) {
|
||||||
@ -1306,6 +1322,7 @@ inline void VM::post_init(){
|
|||||||
init_builtins(this);
|
init_builtins(this);
|
||||||
#if !DEBUG_NO_BUILTIN_MODULES
|
#if !DEBUG_NO_BUILTIN_MODULES
|
||||||
add_module_sys(this);
|
add_module_sys(this);
|
||||||
|
add_module_traceback(this);
|
||||||
add_module_time(this);
|
add_module_time(this);
|
||||||
add_module_json(this);
|
add_module_json(this);
|
||||||
add_module_math(this);
|
add_module_math(this);
|
||||||
|
6
src/vm.h
6
src/vm.h
@ -123,6 +123,8 @@ public:
|
|||||||
PyObject* StopIteration;
|
PyObject* StopIteration;
|
||||||
PyObject* _main; // __main__ module
|
PyObject* _main; // __main__ module
|
||||||
|
|
||||||
|
PyObject* _last_exception;
|
||||||
|
|
||||||
PrintFunc _stdout;
|
PrintFunc _stdout;
|
||||||
PrintFunc _stderr;
|
PrintFunc _stderr;
|
||||||
|
|
||||||
@ -142,6 +144,7 @@ public:
|
|||||||
_stderr = [](VM* vm, const Str& s) { std::cerr << s; };
|
_stderr = [](VM* vm, const Str& s) { std::cerr << s; };
|
||||||
callstack.reserve(8);
|
callstack.reserve(8);
|
||||||
_main = nullptr;
|
_main = nullptr;
|
||||||
|
_last_exception = nullptr;
|
||||||
init_builtin_types();
|
init_builtin_types();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1448,7 +1451,8 @@ inline void ManagedHeap::mark() {
|
|||||||
for(PyObject* obj: _no_gc) OBJ_MARK(obj);
|
for(PyObject* obj: _no_gc) OBJ_MARK(obj);
|
||||||
for(auto& frame : vm->callstack.data()) frame._gc_mark();
|
for(auto& frame : vm->callstack.data()) frame._gc_mark();
|
||||||
for(PyObject* obj: vm->s_data) OBJ_MARK(obj);
|
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){
|
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