mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
...
This commit is contained in:
parent
145782b789
commit
66f7bbd18c
@ -47,6 +47,7 @@ typedef struct VM {
|
|||||||
|
|
||||||
py_TValue last_retval;
|
py_TValue last_retval;
|
||||||
py_TValue curr_exception;
|
py_TValue curr_exception;
|
||||||
|
bool is_curr_exc_handled; // handled by try-except block but not cleared yet
|
||||||
bool is_stopiteration;
|
bool is_stopiteration;
|
||||||
|
|
||||||
py_TValue reg[8]; // users' registers
|
py_TValue reg[8]; // users' registers
|
||||||
|
@ -393,13 +393,16 @@ bool py_exception(py_Type type, const char* fmt, ...) PY_RAISE;
|
|||||||
/// Raise an expection object. Always return false.
|
/// Raise an expection object. Always return false.
|
||||||
bool py_raise(py_Ref) PY_RAISE;
|
bool py_raise(py_Ref) PY_RAISE;
|
||||||
/// Print the current exception.
|
/// Print the current exception.
|
||||||
|
/// The exception will be set as handled.
|
||||||
void py_printexc();
|
void py_printexc();
|
||||||
/// Format the current exception and return a null-terminated string.
|
/// Format the current exception and return a null-terminated string.
|
||||||
/// The result should be freed by the caller.
|
/// The result should be freed by the caller.
|
||||||
|
/// The exception will be set as handled.
|
||||||
char* py_formatexc();
|
char* py_formatexc();
|
||||||
/// Check if an exception is raised.
|
/// Check if an exception is raised.
|
||||||
bool py_checkexc();
|
bool py_checkexc(bool ignore_handled);
|
||||||
/// Check if the exception is an instance of the given type.
|
/// Check if the exception is an instance of the given type.
|
||||||
|
/// If match, the exception will be set as handled.
|
||||||
bool py_matchexc(py_Type type);
|
bool py_matchexc(py_Type type);
|
||||||
/// Clear the current exception.
|
/// Clear the current exception.
|
||||||
/// @param p0 the unwinding point. Use `NULL` if not needed.
|
/// @param p0 the unwinding point. Use `NULL` if not needed.
|
||||||
|
@ -105,7 +105,8 @@ OPCODE(RAISE)
|
|||||||
OPCODE(RAISE_ASSERT)
|
OPCODE(RAISE_ASSERT)
|
||||||
OPCODE(RE_RAISE)
|
OPCODE(RE_RAISE)
|
||||||
OPCODE(PUSH_EXCEPTION)
|
OPCODE(PUSH_EXCEPTION)
|
||||||
OPCODE(POP_EXCEPTION)
|
OPCODE(BEGIN_EXC_HANDLING)
|
||||||
|
OPCODE(END_EXC_HANDLING)
|
||||||
/**************************/
|
/**************************/
|
||||||
OPCODE(FSTRING_EVAL)
|
OPCODE(FSTRING_EVAL)
|
||||||
OPCODE(FORMAT_STRING)
|
OPCODE(FORMAT_STRING)
|
||||||
|
@ -2519,13 +2519,13 @@ static Error* compile_try_except(Compiler* self) {
|
|||||||
}
|
}
|
||||||
int patch = Ctx__emit_(ctx(), OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
int patch = Ctx__emit_(ctx(), OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
||||||
// on match
|
// on match
|
||||||
|
Ctx__emit_(ctx(), OP_BEGIN_EXC_HANDLING, BC_NOARG, BC_KEEPLINE);
|
||||||
if(as_name) {
|
if(as_name) {
|
||||||
Ctx__emit_(ctx(), OP_PUSH_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
Ctx__emit_(ctx(), OP_PUSH_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
||||||
Ctx__emit_store_name(ctx(), name_scope(self), as_name, BC_KEEPLINE);
|
Ctx__emit_store_name(ctx(), name_scope(self), as_name, BC_KEEPLINE);
|
||||||
}
|
}
|
||||||
check(compile_block_body(self, compile_stmt));
|
check(compile_block_body(self, compile_stmt));
|
||||||
// pop the exception
|
Ctx__emit_(ctx(), OP_END_EXC_HANDLING, BC_NOARG, BC_KEEPLINE);
|
||||||
Ctx__emit_(ctx(), OP_POP_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
|
||||||
patches[patches_length++] = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
|
patches[patches_length++] = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
|
||||||
Ctx__patch_jump(ctx(), patch);
|
Ctx__patch_jump(ctx(), patch);
|
||||||
} while(curr()->type == TK_EXCEPT);
|
} while(curr()->type == TK_EXCEPT);
|
||||||
|
@ -1013,7 +1013,11 @@ FrameResult VM__run_top_frame(VM* self) {
|
|||||||
PUSH(&self->curr_exception);
|
PUSH(&self->curr_exception);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
case OP_POP_EXCEPTION: {
|
case OP_BEGIN_EXC_HANDLING: {
|
||||||
|
self->is_curr_exc_handled = true;
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
case OP_END_EXC_HANDLING: {
|
||||||
assert(self->curr_exception.type);
|
assert(self->curr_exception.type);
|
||||||
py_clearexc(NULL);
|
py_clearexc(NULL);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -69,6 +69,7 @@ void VM__ctor(VM* self) {
|
|||||||
|
|
||||||
self->last_retval = *py_NIL;
|
self->last_retval = *py_NIL;
|
||||||
self->curr_exception = *py_NIL;
|
self->curr_exception = *py_NIL;
|
||||||
|
self->is_curr_exc_handled = false;
|
||||||
self->is_stopiteration = false;
|
self->is_stopiteration = false;
|
||||||
|
|
||||||
self->__curr_class = NULL;
|
self->__curr_class = NULL;
|
||||||
|
@ -104,7 +104,7 @@ bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) {
|
|||||||
c11__abort(
|
c11__abort(
|
||||||
"py_CFunction returns nothing! Did you forget to call `py_newnone(py_retval())`?");
|
"py_CFunction returns nothing! Did you forget to call `py_newnone(py_retval())`?");
|
||||||
}
|
}
|
||||||
// if(py_checkexc()) { c11__abort("py_CFunction returns `true` but an exception is set!"); }
|
if(py_checkexc(true)) { c11__abort("py_CFunction returns `true` but an exception is set!"); }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -88,7 +88,11 @@ static bool _py_BaseException__str__(int argc, py_Ref argv) {
|
|||||||
c11_sbuf__ctor(&ss);
|
c11_sbuf__ctor(&ss);
|
||||||
py_Ref arg = py_getslot(argv, 0);
|
py_Ref arg = py_getslot(argv, 0);
|
||||||
if(!py_isnil(arg)) {
|
if(!py_isnil(arg)) {
|
||||||
if(!py_str(arg)) return false;
|
if(argv->type == tp_KeyError) {
|
||||||
|
if(!py_repr(arg)) return false;
|
||||||
|
} else {
|
||||||
|
if(!py_str(arg)) return false;
|
||||||
|
}
|
||||||
c11_sbuf__write_sv(&ss, py_tosv(py_retval()));
|
c11_sbuf__write_sv(&ss, py_tosv(py_retval()));
|
||||||
}
|
}
|
||||||
c11_sbuf__py_submit(&ss, py_retval());
|
c11_sbuf__py_submit(&ss, py_retval());
|
||||||
@ -111,21 +115,29 @@ py_Type pk_Exception__register() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
bool py_checkexc() {
|
bool py_checkexc(bool ignore_handled) {
|
||||||
VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
|
if(ignore_handled && vm->is_curr_exc_handled) return false;
|
||||||
return !py_isnil(&vm->curr_exception);
|
return !py_isnil(&vm->curr_exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool py_matchexc(py_Type type) {
|
bool py_matchexc(py_Type type) {
|
||||||
VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
|
if(vm->is_curr_exc_handled) return false;
|
||||||
if(py_isnil(&vm->curr_exception)) return false;
|
if(py_isnil(&vm->curr_exception)) return false;
|
||||||
return py_issubclass(vm->curr_exception.type, type);
|
bool ok = py_issubclass(vm->curr_exception.type, type);
|
||||||
|
if(ok) {
|
||||||
|
// if match, then the exception is handled
|
||||||
|
vm->is_curr_exc_handled = true;
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void py_clearexc(py_StackRef p0) {
|
void py_clearexc(py_StackRef p0) {
|
||||||
VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
vm->last_retval = *py_NIL;
|
vm->last_retval = *py_NIL;
|
||||||
vm->curr_exception = *py_NIL;
|
vm->curr_exception = *py_NIL;
|
||||||
|
vm->is_curr_exc_handled = false;
|
||||||
vm->is_stopiteration = false;
|
vm->is_stopiteration = false;
|
||||||
vm->__curr_class = NULL;
|
vm->__curr_class = NULL;
|
||||||
if(p0) vm->stack.sp = p0;
|
if(p0) vm->stack.sp = p0;
|
||||||
@ -155,9 +167,13 @@ static void c11_sbuf__write_exc(c11_sbuf* self, py_Ref exc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char* name = py_tpname(exc->type);
|
const char* name = py_tpname(exc->type);
|
||||||
|
const char* message;
|
||||||
bool ok = py_str(exc);
|
bool ok = py_str(exc);
|
||||||
if(!ok) c11__abort("py_printexc(): failed to convert exception to string");
|
if(!ok || !py_isstr(py_retval())) {
|
||||||
const char* message = py_tostr(py_retval());
|
message = "<exception str() failed>";
|
||||||
|
} else {
|
||||||
|
message = py_tostr(py_retval());
|
||||||
|
}
|
||||||
|
|
||||||
c11_sbuf__write_cstr(self, name);
|
c11_sbuf__write_cstr(self, name);
|
||||||
c11_sbuf__write_cstr(self, ": ");
|
c11_sbuf__write_cstr(self, ": ");
|
||||||
@ -167,6 +183,10 @@ static void c11_sbuf__write_exc(c11_sbuf* self, py_Ref exc) {
|
|||||||
char* py_formatexc() {
|
char* py_formatexc() {
|
||||||
VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
if(py_isnil(&vm->curr_exception)) return NULL;
|
if(py_isnil(&vm->curr_exception)) return NULL;
|
||||||
|
|
||||||
|
// when you call `py_formatexc()`, you are handling the exception
|
||||||
|
vm->is_curr_exc_handled = true;
|
||||||
|
|
||||||
c11_sbuf ss;
|
c11_sbuf ss;
|
||||||
c11_sbuf__ctor(&ss);
|
c11_sbuf__ctor(&ss);
|
||||||
|
|
||||||
@ -215,6 +235,7 @@ bool py_raise(py_Ref exc) {
|
|||||||
py_setslot(exc, 1, &vm->curr_exception);
|
py_setslot(exc, 1, &vm->curr_exception);
|
||||||
}
|
}
|
||||||
vm->curr_exception = *exc;
|
vm->curr_exception = *exc;
|
||||||
|
vm->is_curr_exc_handled = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int code = py_checkexc() ? 1 : 0;
|
int code = py_checkexc(false) ? 1 : 0;
|
||||||
py_finalize();
|
py_finalize();
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,9 @@ try:
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
k = KeyError('foo')
|
||||||
|
assert str(k) == "'foo'"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
assert False
|
assert False
|
||||||
exit(1)
|
exit(1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user