50
50
Integer ,
51
51
LoadAddress ,
52
52
LoadErrorValue ,
53
+ MethodCall ,
53
54
RaiseStandardError ,
54
55
Register ,
55
56
Return ,
61
62
RInstance ,
62
63
exc_rtuple ,
63
64
is_tagged ,
65
+ none_rprimitive ,
64
66
object_pointer_rprimitive ,
65
67
object_rprimitive ,
66
68
)
@@ -657,14 +659,45 @@ def transform_with(
657
659
al = "a" if is_async else ""
658
660
659
661
mgr_v = builder .accept (expr )
660
- typ = builder .call_c (type_op , [mgr_v ], line )
661
- exit_ = builder .maybe_spill (builder .py_get_attr (typ , f"__{ al } exit__" , line ))
662
- value = builder .py_call (builder .py_get_attr (typ , f"__{ al } enter__" , line ), [mgr_v ], line )
662
+ is_native = isinstance (mgr_v .type , RInstance )
663
+ if is_native :
664
+ value = builder .add (MethodCall (mgr_v , f"__{ al } enter__" , args = [], line = line ))
665
+ exit_ = None
666
+ else :
667
+ typ = builder .call_c (type_op , [mgr_v ], line )
668
+ exit_ = builder .maybe_spill (builder .py_get_attr (typ , f"__{ al } exit__" , line ))
669
+ value = builder .py_call (builder .py_get_attr (typ , f"__{ al } enter__" , line ), [mgr_v ], line )
670
+
663
671
mgr = builder .maybe_spill (mgr_v )
664
672
exc = builder .maybe_spill_assignable (builder .true ())
665
673
if is_async :
666
674
value = emit_await (builder , value , line )
667
675
676
+ def maybe_natively_call_exit (exc_info : bool ) -> Value :
677
+ if exc_info :
678
+ args = get_sys_exc_info (builder )
679
+ else :
680
+ none = builder .none_object ()
681
+ args = [none , none , none ]
682
+
683
+ if is_native :
684
+ assert isinstance (mgr_v .type , RInstance )
685
+ exit_val = builder .gen_method_call (
686
+ builder .read (mgr ),
687
+ f"__{ al } exit__" ,
688
+ arg_values = args ,
689
+ line = line ,
690
+ result_type = none_rprimitive ,
691
+ )
692
+ else :
693
+ assert exit_ is not None
694
+ exit_val = builder .py_call (builder .read (exit_ ), [builder .read (mgr )] + args , line )
695
+
696
+ if is_async :
697
+ return emit_await (builder , exit_val , line )
698
+ else :
699
+ return exit_val
700
+
668
701
def try_body () -> None :
669
702
if target :
670
703
builder .assign (builder .get_assignment_target (target ), value , line )
@@ -673,13 +706,7 @@ def try_body() -> None:
673
706
def except_body () -> None :
674
707
builder .assign (exc , builder .false (), line )
675
708
out_block , reraise_block = BasicBlock (), BasicBlock ()
676
- exit_val = builder .py_call (
677
- builder .read (exit_ ), [builder .read (mgr )] + get_sys_exc_info (builder ), line
678
- )
679
- if is_async :
680
- exit_val = emit_await (builder , exit_val , line )
681
-
682
- builder .add_bool_branch (exit_val , out_block , reraise_block )
709
+ builder .add_bool_branch (maybe_natively_call_exit (exc_info = True ), out_block , reraise_block )
683
710
builder .activate_block (reraise_block )
684
711
builder .call_c (reraise_exception_op , [], NO_TRACEBACK_LINE_NO )
685
712
builder .add (Unreachable ())
@@ -689,13 +716,8 @@ def finally_body() -> None:
689
716
out_block , exit_block = BasicBlock (), BasicBlock ()
690
717
builder .add (Branch (builder .read (exc ), exit_block , out_block , Branch .BOOL ))
691
718
builder .activate_block (exit_block )
692
- none = builder .none_object ()
693
- exit_val = builder .py_call (
694
- builder .read (exit_ ), [builder .read (mgr ), none , none , none ], line
695
- )
696
- if is_async :
697
- emit_await (builder , exit_val , line )
698
719
720
+ maybe_natively_call_exit (exc_info = False )
699
721
builder .goto_and_activate (out_block )
700
722
701
723
transform_try_finally_stmt (
0 commit comments