experimental support for try..except..as

This commit is contained in:
blueloveTH 2023-12-04 18:06:02 +08:00
parent 34f3ac32e7
commit f6942e0caf
6 changed files with 43 additions and 5 deletions

View File

@ -61,7 +61,9 @@ struct Exception {
Exception(StrName type, Str msg): Exception(StrName type, Str msg):
type(type), msg(msg), is_re(true), _ip_on_error(-1), _code_on_error(nullptr) {} type(type), msg(msg), is_re(true), _ip_on_error(-1), _code_on_error(nullptr) {}
bool match_type(StrName t) const { return this->type == t;} bool match_type(StrName t) const {
return this->type==t || t.sv()=="Exception";
}
template<typename... Args> template<typename... Args>
void st_push(Args&&... args){ void st_push(Args&&... args){

View File

@ -258,7 +258,6 @@ def help(obj):
class Exception: pass class Exception: pass
class classmethod: class classmethod:
def __init__(self, f): def __init__(self, f):
self.f = f self.f = f

View File

@ -677,14 +677,24 @@ __EAT_DOTS_END:
}; };
ctx()->exit_block(); ctx()->exit_block();
do { do {
StrName as_name;
consume(TK("except")); consume(TK("except"));
if(match(TK("@id"))){ if(match(TK("@id"))){
ctx()->emit_(OP_EXCEPTION_MATCH, StrName(prev().sv()).index, prev().line); ctx()->emit_(OP_EXCEPTION_MATCH, StrName(prev().sv()).index, prev().line);
if(match(TK("as"))){
consume(TK("@id"));
as_name = StrName(prev().sv());
}
}else{ }else{
ctx()->emit_(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE); ctx()->emit_(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
} }
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 // on match
if(!as_name.empty()){
ctx()->emit_(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
ctx()->emit_store_name(name_scope(), as_name, BC_KEEPLINE);
}
// pop the exception
ctx()->emit_(OP_POP_EXCEPTION, 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));

View File

@ -1318,6 +1318,17 @@ void init_builtins(VM* _vm) {
// return args[0]; // return args[0];
// }); // });
// Exception
_vm->bind__repr__(_vm->tp_exception, [](VM* vm, PyObject* obj) {
Exception& self = _CAST(Exception&, obj);
return VAR(fmt(self.type.sv(), '(', self.msg.escape(), ')'));
});
_vm->bind__str__(_vm->tp_exception, [](VM* vm, PyObject* obj) {
Exception& self = _CAST(Exception&, obj);
return VAR(self.msg);
});
RangeIter::register_class(_vm, _vm->builtins); RangeIter::register_class(_vm, _vm->builtins);
ArrayIter::register_class(_vm, _vm->builtins); ArrayIter::register_class(_vm, _vm->builtins);
StringIter::register_class(_vm, _vm->builtins); StringIter::register_class(_vm, _vm->builtins);

View File

@ -724,7 +724,7 @@ void VM::init_builtin_types(){
tp_native_func = _new_type_object("native_func"); tp_native_func = _new_type_object("native_func");
tp_bound_method = _new_type_object("bound_method"); tp_bound_method = _new_type_object("bound_method");
tp_super = _new_type_object("super"); tp_super = _new_type_object("super");
tp_exception = _new_type_object("Exception"); tp_exception = _new_type_object("_Exception");
tp_bytes = _new_type_object("bytes"); tp_bytes = _new_type_object("bytes");
tp_mappingproxy = _new_type_object("mappingproxy"); tp_mappingproxy = _new_type_object("mappingproxy");
tp_dict = _new_type_object("dict"); tp_dict = _new_type_object("dict");

View File

@ -81,4 +81,20 @@ def f(a: list):
a[0] = 1 a[0] = 1
a = [0] a = [0]
f(a) f(a)
assert a == [1] assert a == [1]
try:
a = [][3]
except IndexError as e:
assert str(e) == '3 not in [0, 0)'
assert repr(e).startswith('IndexError(')
try:
a = {}[2]
except IndexError as e:
exit(1)
except Exception as e:
assert str(e) == '2'
assert repr(e).startswith('KeyError(')
except:
exit(1)