diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py index de764d9d749..a698f5a7a02 100644 --- a/pypy/interpreter/astcompiler/codegen.py +++ b/pypy/interpreter/astcompiler/codegen.py @@ -1083,17 +1083,42 @@ def visit_TryStar(self, tr): self.load_const(self.space.w_None) self.emit_op(ops.IS_OP) self.emit_jump(ops.POP_JUMP_IF_TRUE, pop_next_except) - if handler.name is None: - self.emit_op(ops.POP_TOP) - else: - assert 0, "implement me" + exception_in_exc_body = self.new_block() # R1 in comment above + cleanup_body = self.new_block() + if handler.name is not None: + self.name_op(handler.name, ast.Store, handler) + else: + self.emit_op(ops.POP_TOP) + ## generate the equivalent of: + ## + ## try: + ## < body > + ## except* type as name: + ## try: + ## < body > + ## name = None + ## del name + ## except: + ## name = None + ## del name + ## continue with except* handling + # self.emit_jump(ops.SETUP_EXCEPT, exception_in_exc_body) self._visit_body(handler.body) self.emit_op(ops.POP_BLOCK) # XXX missing in CPython comment + if handler.name: + self.load_const(self.space.w_None) + self.name_op(handler.name, ast.Store, handler) + self.name_op(handler.name, ast.Del, handler) self.emit_jump(ops.JUMP_FORWARD, next_except_with_nop) self.use_next_block(exception_in_exc_body) + if handler.name: + self.load_const(self.space.w_None) + self.name_op(handler.name, ast.Store, handler) + self.name_op(handler.name, ast.Del, handler) + self.emit_op(ops.POP_TOP) # get rid of type self.emit_op_arg(ops.LIST_APPEND, 3) self.emit_op(ops.POP_TOP) diff --git a/pypy/interpreter/astcompiler/test/apptest_exceptiongroup.py b/pypy/interpreter/astcompiler/test/apptest_exceptiongroup.py index fc7a5407274..d35cb9f7005 100644 --- a/pypy/interpreter/astcompiler/test/apptest_exceptiongroup.py +++ b/pypy/interpreter/astcompiler/test/apptest_exceptiongroup.py @@ -52,19 +52,34 @@ def test_error_in_exception_handler(): assert 0, "an ExceptionGroup should be raised" def test_name_except_star(): + l = [] + value = ValueError() + typ = TypeError() try: - raise TypeError() + raise ExceptionGroup('abc', [value, typ]) except* TypeError as e1: - a = 1 - assert e1 is exc + assert e1.exceptions[0] is typ + l.append(1) except* ValueError as e2: - assert 0, "unreachable" - assert a == 1 + assert e2.exceptions[0] is value + l.append(2) + print(l) + assert l == [1, 2] with raises(UnboundLocalError): e1 + with raises(UnboundLocalError): + e2 -def test_bare_except_star(): +def test_try_star_name_raise_in_except_handler(): + l = [] + value = ValueError() + typ = TypeError() try: - raise TypeError() - except*: - pass + try: + raise ExceptionGroup('abc', [value, typ]) + except* TypeError as e1: + 1 / 0 + except Exception as e: + assert "ZeroDivisionError" in repr(e) + with raises(UnboundLocalError): + e1 diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py index 94544f92d50..1e7d7be1f68 100644 --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -1806,7 +1806,6 @@ def CHECK_EG_MATCH(self, oparg, next_instr): self.pushvalue(w_match) def PREP_RERAISE_STAR(self, oparg, next_instr): - # TODO: Implement space = self.space w_res = self.popvalue() w_orig = self.popvalue()