5050 Integer ,
5151 LoadAddress ,
5252 LoadErrorValue ,
53+ MethodCall ,
5354 RaiseStandardError ,
5455 Register ,
5556 Return ,
6162 RInstance ,
6263 exc_rtuple ,
6364 is_tagged ,
65+ none_rprimitive ,
6466 object_pointer_rprimitive ,
6567 object_rprimitive ,
6668)
@@ -657,14 +659,45 @@ def transform_with(
657659 al = "a" if is_async else ""
658660
659661 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+
663671 mgr = builder .maybe_spill (mgr_v )
664672 exc = builder .maybe_spill_assignable (builder .true ())
665673 if is_async :
666674 value = emit_await (builder , value , line )
667675
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+
668701 def try_body () -> None :
669702 if target :
670703 builder .assign (builder .get_assignment_target (target ), value , line )
@@ -673,13 +706,7 @@ def try_body() -> None:
673706 def except_body () -> None :
674707 builder .assign (exc , builder .false (), line )
675708 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 )
683710 builder .activate_block (reraise_block )
684711 builder .call_c (reraise_exception_op , [], NO_TRACEBACK_LINE_NO )
685712 builder .add (Unreachable ())
@@ -689,13 +716,8 @@ def finally_body() -> None:
689716 out_block , exit_block = BasicBlock (), BasicBlock ()
690717 builder .add (Branch (builder .read (exc ), exit_block , out_block , Branch .BOOL ))
691718 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 )
698719
720+ maybe_natively_call_exit (exc_info = False )
699721 builder .goto_and_activate (out_block )
700722
701723 transform_try_finally_stmt (
0 commit comments