mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20: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 curr_exception;
|
||||
bool is_curr_exc_handled; // handled by try-except block but not cleared yet
|
||||
bool is_stopiteration;
|
||||
|
||||
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.
|
||||
bool py_raise(py_Ref) PY_RAISE;
|
||||
/// Print the current exception.
|
||||
/// The exception will be set as handled.
|
||||
void py_printexc();
|
||||
/// Format the current exception and return a null-terminated string.
|
||||
/// The result should be freed by the caller.
|
||||
/// The exception will be set as handled.
|
||||
char* py_formatexc();
|
||||
/// 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.
|
||||
/// If match, the exception will be set as handled.
|
||||
bool py_matchexc(py_Type type);
|
||||
/// Clear the current exception.
|
||||
/// @param p0 the unwinding point. Use `NULL` if not needed.
|
||||
|
@ -105,7 +105,8 @@ OPCODE(RAISE)
|
||||
OPCODE(RAISE_ASSERT)
|
||||
OPCODE(RE_RAISE)
|
||||
OPCODE(PUSH_EXCEPTION)
|
||||
OPCODE(POP_EXCEPTION)
|
||||
OPCODE(BEGIN_EXC_HANDLING)
|
||||
OPCODE(END_EXC_HANDLING)
|
||||
/**************************/
|
||||
OPCODE(FSTRING_EVAL)
|
||||
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);
|
||||
// on match
|
||||
Ctx__emit_(ctx(), OP_BEGIN_EXC_HANDLING, BC_NOARG, BC_KEEPLINE);
|
||||
if(as_name) {
|
||||
Ctx__emit_(ctx(), OP_PUSH_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
||||
Ctx__emit_store_name(ctx(), name_scope(self), as_name, BC_KEEPLINE);
|
||||
}
|
||||
check(compile_block_body(self, compile_stmt));
|
||||
// pop the exception
|
||||
Ctx__emit_(ctx(), OP_POP_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
||||
Ctx__emit_(ctx(), OP_END_EXC_HANDLING, BC_NOARG, BC_KEEPLINE);
|
||||
patches[patches_length++] = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
|
||||
Ctx__patch_jump(ctx(), patch);
|
||||
} while(curr()->type == TK_EXCEPT);
|
||||
|
@ -1013,7 +1013,11 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
PUSH(&self->curr_exception);
|
||||
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);
|
||||
py_clearexc(NULL);
|
||||
DISPATCH();
|
||||
|
@ -69,6 +69,7 @@ void VM__ctor(VM* self) {
|
||||
|
||||
self->last_retval = *py_NIL;
|
||||
self->curr_exception = *py_NIL;
|
||||
self->is_curr_exc_handled = false;
|
||||
self->is_stopiteration = false;
|
||||
|
||||
self->__curr_class = NULL;
|
||||
|
@ -104,7 +104,7 @@ bool py_callcfunc(py_CFunction f, int argc, py_Ref argv) {
|
||||
c11__abort(
|
||||
"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;
|
||||
}
|
||||
#endif
|
||||
|
@ -88,7 +88,11 @@ static bool _py_BaseException__str__(int argc, py_Ref argv) {
|
||||
c11_sbuf__ctor(&ss);
|
||||
py_Ref arg = py_getslot(argv, 0);
|
||||
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__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;
|
||||
if(ignore_handled && vm->is_curr_exc_handled) return false;
|
||||
return !py_isnil(&vm->curr_exception);
|
||||
}
|
||||
|
||||
bool py_matchexc(py_Type type) {
|
||||
VM* vm = pk_current_vm;
|
||||
if(vm->is_curr_exc_handled) 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) {
|
||||
VM* vm = pk_current_vm;
|
||||
vm->last_retval = *py_NIL;
|
||||
vm->curr_exception = *py_NIL;
|
||||
vm->is_curr_exc_handled = false;
|
||||
vm->is_stopiteration = false;
|
||||
vm->__curr_class = NULL;
|
||||
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* message;
|
||||
bool ok = py_str(exc);
|
||||
if(!ok) c11__abort("py_printexc(): failed to convert exception to string");
|
||||
const char* message = py_tostr(py_retval());
|
||||
if(!ok || !py_isstr(py_retval())) {
|
||||
message = "<exception str() failed>";
|
||||
} else {
|
||||
message = py_tostr(py_retval());
|
||||
}
|
||||
|
||||
c11_sbuf__write_cstr(self, name);
|
||||
c11_sbuf__write_cstr(self, ": ");
|
||||
@ -167,6 +183,10 @@ static void c11_sbuf__write_exc(c11_sbuf* self, py_Ref exc) {
|
||||
char* py_formatexc() {
|
||||
VM* vm = pk_current_vm;
|
||||
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__ctor(&ss);
|
||||
|
||||
@ -215,6 +235,7 @@ bool py_raise(py_Ref exc) {
|
||||
py_setslot(exc, 1, &vm->curr_exception);
|
||||
}
|
||||
vm->curr_exception = *exc;
|
||||
vm->is_curr_exc_handled = 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();
|
||||
return code;
|
||||
}
|
||||
|
@ -7,6 +7,9 @@ try:
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
k = KeyError('foo')
|
||||
assert str(k) == "'foo'"
|
||||
|
||||
try:
|
||||
assert False
|
||||
exit(1)
|
||||
|
Loading…
x
Reference in New Issue
Block a user