diff --git a/README.md b/README.md index 71aad9cc..f433a131 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,7 @@ __ERROR: | F-String | `f'value is {x}'` | ✅ | | Unpacking | `a, b = 1, 2` | ✅ | | Star Unpacking | `a, *b = [1, 2, 3]` | ✅ | -| Exception | `raise/try..catch..finally` | ✅ | +| Exception | `raise/try..except..` | ✅ | | Dynamic Code | `eval()/exec()` | ✅ | | Reflection | `hasattr()/getattr()/setattr()` | ✅ | | Import | `import/from..import` | ✅ | diff --git a/docs/features/basic.md b/docs/features/basic.md index 0ece257a..138936da 100644 --- a/docs/features/basic.md +++ b/docs/features/basic.md @@ -20,7 +20,7 @@ The following table shows the basic features of pkpy with respect to [cpython](h | F-String | `f'value is {x}'` | ✅ | | Unpacking | `a, b = 1, 2` | ✅ | | Star Unpacking | `a, *b = [1, 2, 3]` | ✅ | -| Exception | `raise/try..catch..finally` | ✅ | +| Exception | `raise/try..except..` | ✅ | | Dynamic Code | `eval()/exec()` | ✅ | | Reflection | `hasattr()/getattr()/setattr()` | ✅ | | Import | `import/from..import` | ✅ | diff --git a/include/pocketpy/objects/codeobject.h b/include/pocketpy/objects/codeobject.h index 88af8a55..4d61e98f 100644 --- a/include/pocketpy/objects/codeobject.h +++ b/include/pocketpy/objects/codeobject.h @@ -35,7 +35,6 @@ typedef enum CodeBlockType { CodeBlockType_WITH, /* context blocks (flag-based) */ CodeBlockType_EXCEPT, - CodeBlockType_FINALLY, } CodeBlockType; typedef enum Opcode { diff --git a/include/pocketpy/xmacros/opcodes.h b/include/pocketpy/xmacros/opcodes.h index 99f3e448..f4cf9ac4 100644 --- a/include/pocketpy/xmacros/opcodes.h +++ b/include/pocketpy/xmacros/opcodes.h @@ -124,8 +124,6 @@ OPCODE(RE_RAISE) OPCODE(PUSH_EXCEPTION) OPCODE(BEGIN_EXC_HANDLING) OPCODE(END_EXC_HANDLING) -OPCODE(BEGIN_FINALLY) -OPCODE(END_FINALLY) /**************************/ OPCODE(FORMAT_STRING) /**************************/ diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index d1c3b9d0..1cd5106a 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -1136,10 +1136,6 @@ static int Ctx__prepare_loop_divert(Ctx* self, int line, bool is_break) { Ctx__emit_(self, OP_END_EXC_HANDLING, 1, line); break; } - case CodeBlockType_FINALLY: { - Ctx__emit_(self, OP_END_FINALLY, 1, line); - break; - } default: break; } index = block->parent; @@ -2000,7 +1996,7 @@ static Error* exprSlice0(Compiler* self) { check(EXPR(self)); slice->step = Ctx__s_popx(ctx()); } // else :: - } // else : + } // else : return NULL; } @@ -2646,21 +2642,11 @@ static Error* compile_try_except(Compiler* self) { bool has_finally = curr()->type == TK_FINALLY; if(!has_finally) { patches[patches_length++] = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE); + } else { + return SyntaxError(self, "finally clause is not supported yet"); } - Ctx__exit_block(ctx()); - if(has_finally) { - consume(TK_FINALLY); - Ctx__emit_(ctx(), OP_BEGIN_FINALLY, BC_NOARG, prev()->line); - // finally only, no except block - Ctx__enter_block(ctx(), CodeBlockType_FINALLY); - check(compile_block_body(self)); - Ctx__exit_block(ctx()); - Ctx__emit_(ctx(), OP_END_FINALLY, BC_NOARG, BC_KEEPLINE); - // re-raise if needed - Ctx__emit_(ctx(), OP_RE_RAISE, BC_NOARG, BC_KEEPLINE); - return NULL; - } + Ctx__exit_block(ctx()); do { if(patches_length == 8) { @@ -2701,16 +2687,12 @@ static Error* compile_try_except(Compiler* self) { // ... // match one & handled, jump to the end - for(int i = 0; i < patches_length; i++) + for(int i = 0; i < patches_length; i++) { Ctx__patch_jump(ctx(), patches[i]); - - if(match(TK_FINALLY)) { - Ctx__emit_(ctx(), OP_BEGIN_FINALLY, BC_NOARG, prev()->line); - Ctx__enter_block(ctx(), CodeBlockType_FINALLY); - check(compile_block_body(self)); - Ctx__exit_block(ctx()); - Ctx__emit_(ctx(), OP_END_FINALLY, BC_NOARG, BC_KEEPLINE); } + + if(match(TK_FINALLY)) { return SyntaxError(self, "finally clause is not supported yet"); } + // re-raise if needed Ctx__emit_(ctx(), OP_RE_RAISE, BC_NOARG, BC_KEEPLINE); return NULL; diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index 4bcac41d..b0734801 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -1190,27 +1190,6 @@ __NEXT_STEP: py_clearexc(NULL); DISPATCH(); } - case OP_BEGIN_FINALLY: { - if(self->curr_exception.type) { - assert(!self->is_curr_exc_handled); - // temporarily handle the exception if any - self->is_curr_exc_handled = true; - } - DISPATCH(); - } - case OP_END_FINALLY: { - if(byte.arg == BC_NOARG) { - if(self->curr_exception.type) { - assert(self->is_curr_exc_handled); - // revert the exception handling if needed - self->is_curr_exc_handled = false; - } - } else { - // break or continue inside finally block - py_clearexc(NULL); - } - DISPATCH(); - } ////////////////// case OP_FORMAT_STRING: { py_Ref spec = c11__at(py_TValue, &frame->co->consts, byte.arg); diff --git a/tests/28_exception.py b/tests/28_exception.py index adeabe21..5fdd20f8 100644 --- a/tests/28_exception.py +++ b/tests/28_exception.py @@ -146,7 +146,20 @@ except SyntaxError as e: ok = True assert ok +# nested try +def g(): + try: + raise KeyError + except KeyError: + pass +if 0: + try: + raise IndexError + except IndexError: + g() + +""" # finally, only def finally_only(): try: @@ -224,18 +237,4 @@ def finally_return(): return 1 assert finally_return() == 1 - - -# nested try -def g(): - try: - raise KeyError - except KeyError: - pass - -if 0: - try: - raise IndexError - except IndexError: - g() - +"""