|
|
@@ -673,34 +673,56 @@ __EAT_DOTS_END:
|
|
|
ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE)
|
|
|
};
|
|
|
ctx()->exit_block();
|
|
|
- do {
|
|
|
- StrName as_name;
|
|
|
- consume(TK("except"));
|
|
|
- if(is_expression()){
|
|
|
- EXPR(false); // push assumed type on to the stack
|
|
|
- ctx()->emit_(OP_EXCEPTION_MATCH, BC_NOARG, prev().line);
|
|
|
- if(match(TK("as"))){
|
|
|
- consume(TK("@id"));
|
|
|
- as_name = StrName(prev().sv());
|
|
|
+
|
|
|
+ int finally_entry = -1;
|
|
|
+ if(curr().type != TK("finally")){
|
|
|
+ do {
|
|
|
+ StrName as_name;
|
|
|
+ consume(TK("except"));
|
|
|
+ if(is_expression()){
|
|
|
+ EXPR(false); // push assumed type on to the stack
|
|
|
+ ctx()->emit_(OP_EXCEPTION_MATCH, BC_NOARG, prev().line);
|
|
|
+ if(match(TK("as"))){
|
|
|
+ consume(TK("@id"));
|
|
|
+ as_name = StrName(prev().sv());
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ ctx()->emit_(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
|
|
|
}
|
|
|
- }else{
|
|
|
- ctx()->emit_(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
|
|
|
- }
|
|
|
- int patch = ctx()->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
|
|
- // 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);
|
|
|
+ int patch = ctx()->emit_(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
|
|
+ // 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);
|
|
|
+ compile_block_body();
|
|
|
+ patches.push_back(ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE));
|
|
|
+ ctx()->patch_jump(patch);
|
|
|
+ }while(curr().type == TK("except"));
|
|
|
+ }
|
|
|
+
|
|
|
+ if(match(TK("finally"))){
|
|
|
+ int patch = ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE);
|
|
|
+ finally_entry = ctx()->co->codes.size();
|
|
|
compile_block_body();
|
|
|
- patches.push_back(ctx()->emit_(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE));
|
|
|
+ ctx()->emit_(OP_JUMP_ABSOLUTE_TOP, BC_NOARG, BC_KEEPLINE);
|
|
|
ctx()->patch_jump(patch);
|
|
|
- }while(curr().type == TK("except"));
|
|
|
+ }
|
|
|
// no match, re-raise
|
|
|
+ if(finally_entry != -1){
|
|
|
+ ctx()->emit_(OP_LOAD_INTEGER, (uint16_t)ctx()->co->codes.size()+2, BC_KEEPLINE);
|
|
|
+ ctx()->emit_(OP_JUMP_ABSOLUTE, finally_entry, BC_KEEPLINE);
|
|
|
+ }
|
|
|
ctx()->emit_(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
|
|
|
+
|
|
|
+ // no exception or no match, jump to the end
|
|
|
for (int patch : patches) ctx()->patch_jump(patch);
|
|
|
+ if(finally_entry != -1){
|
|
|
+ ctx()->emit_(OP_LOAD_INTEGER, (uint16_t)ctx()->co->codes.size()+2, BC_KEEPLINE);
|
|
|
+ ctx()->emit_(OP_JUMP_ABSOLUTE, finally_entry, BC_KEEPLINE);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void Compiler::compile_decorated(){
|