114114 no_err_occurred_op ,
115115 propagate_if_error_op ,
116116 raise_exception_op ,
117+ raise_exception_with_tb_op ,
117118 reraise_exception_op ,
118119 restore_exc_info_op ,
119120)
@@ -1053,7 +1054,7 @@ def _transform_with_contextmanager(
10531054 expr .arg_names ,
10541055 )
10551056 wrapped_call .line = line
1056- gen = builder .accept (wrapped_call )
1057+ gen = builder .maybe_spill ( builder . accept (wrapped_call ) )
10571058
10581059 def raise_runtime_error_from_none (msg : str ) -> None :
10591060 runtime_error = builder .load_module_attr_by_fullname ("builtins.RuntimeError" , line )
@@ -1077,7 +1078,7 @@ def raise_runtime_error_from_none(msg: str) -> None:
10771078 # target = next(gen)
10781079 # except StopIteration:
10791080 # raise RuntimeError("generator didn't yield") from None
1080- mgr_target = builder .call_c (next_raw_op , [gen ], line )
1081+ mgr_target = builder .call_c (next_raw_op , [builder . read ( gen ) ], line )
10811082
10821083 runtime_block , main_block = BasicBlock (), BasicBlock ()
10831084 builder .add (Branch (mgr_target , runtime_block , main_block , Branch .IS_ERROR ))
@@ -1117,33 +1118,57 @@ def try_body() -> None:
11171118 builder .assign (builder .get_assignment_target (target ), mgr_target , line )
11181119 with_body ()
11191120
1120- # except Exception as e:
1121+ # except BaseException as e:
11211122 # try:
1122- # gen.throw(e )
1123+ # gen.throw(type, value, traceback )
11231124 # except StopIteration as e2:
11241125 # if e2 is not e:
11251126 # raise
11261127 # return
11271128 # except RuntimeError:
1128- # # TODO: check the traceback munging
11291129 # raise
11301130 # except BaseException:
11311131 # # approximately
11321132 # raise
11331133
11341134 def except_body () -> None :
1135- exc_original = builder .call_c (get_exc_value_op , [], line )
1135+ exc_info = builder .call_c (get_exc_info_op , [], line )
1136+ exc_type = builder .add (TupleGet (exc_info , 0 , line ))
1137+ exc_value = builder .add (TupleGet (exc_info , 1 , line ))
1138+ exc_tb = builder .add (TupleGet (exc_info , 2 , line ))
1139+ exc_value_target = builder .maybe_spill_assignable (exc_value )
1140+
1141+ def reraise_original () -> None :
1142+ builder .call_c (
1143+ raise_exception_with_tb_op ,
1144+ [exc_type , builder .read (exc_value_target ), exc_tb ],
1145+ line ,
1146+ )
1147+ builder .add (Unreachable ())
1148+
1149+ # Make sure we have an exception instance so identity comparisons are reliable.
1150+ none = builder .none_object ()
1151+ is_none = builder .binary_op (builder .read (exc_value_target ), none , "is" , line )
1152+ value_block , value_done = BasicBlock (), BasicBlock ()
1153+ builder .add (Branch (is_none , value_block , value_done , Branch .BOOL ))
1154+ builder .activate_block (value_block )
1155+ new_value = builder .py_call (exc_type , [], line )
1156+ builder .assign (exc_value_target , new_value , line )
1157+ builder .goto (value_done )
1158+ builder .activate_block (value_done )
11361159
11371160 error_block , no_error_block = BasicBlock (), BasicBlock ()
1138-
11391161 builder .builder .push_error_handler (error_block )
11401162 builder .goto_and_activate (BasicBlock ())
1141- builder .py_call (builder .py_get_attr (gen , "throw" , line ), [exc_original ], line )
1163+ builder .py_call (
1164+ builder .py_get_attr (builder .read (gen ), "throw" , line ),
1165+ [exc_type , builder .read (exc_value_target ), exc_tb ],
1166+ line ,
1167+ )
11421168 builder .goto (no_error_block )
11431169 builder .builder .pop_error_handler ()
11441170
11451171 builder .activate_block (no_error_block )
1146- builder .py_call (builder .py_get_attr (gen , "close" , line ), [], line )
11471172 builder .add (
11481173 RaiseStandardError (
11491174 RaiseStandardError .RUNTIME_ERROR , "generator didn't stop after throw()" , line
@@ -1155,21 +1180,67 @@ def except_body() -> None:
11551180 throw_old_exc = builder .maybe_spill (builder .call_c (error_catch_op , [], line ))
11561181 stop_iteration = builder .load_module_attr_by_fullname ("builtins.StopIteration" , line )
11571182 is_stop_iteration = builder .call_c (exc_matches_op , [stop_iteration ], line )
1158- stop_block , propagate_block = BasicBlock (), BasicBlock ()
1159- builder .add (Branch (is_stop_iteration , stop_block , propagate_block , Branch .BOOL ))
1183+ stop_block , runtime_check_block = BasicBlock (), BasicBlock ()
1184+ builder .add (Branch (is_stop_iteration , stop_block , runtime_check_block , Branch .BOOL ))
1185+
1186+ suppress_block = BasicBlock ()
1187+
1188+ builder .activate_block (stop_block )
1189+ stop_exc = builder .call_c (get_exc_value_op , [], line )
1190+ is_same_exc = builder .binary_op (stop_exc , builder .read (exc_value_target ), "is" , line )
1191+ propagate_block = BasicBlock ()
1192+ builder .add (Branch (is_same_exc , propagate_block , suppress_block , Branch .BOOL ))
11601193
11611194 builder .activate_block (propagate_block )
1195+ reraise_original ()
1196+
1197+ builder .activate_block (runtime_check_block )
1198+ runtime_error = builder .load_module_attr_by_fullname ("builtins.RuntimeError" , line )
1199+ is_runtime_error = builder .call_c (exc_matches_op , [runtime_error ], line )
1200+ runtime_block , other_block = BasicBlock (), BasicBlock ()
1201+ builder .add (Branch (is_runtime_error , runtime_block , other_block , Branch .BOOL ))
1202+
1203+ builder .activate_block (runtime_block )
1204+ runtime_exc = builder .call_c (get_exc_value_op , [], line )
1205+ is_same_runtime = builder .binary_op (runtime_exc , builder .read (exc_value_target ), "is" , line )
1206+ runtime_same_block , runtime_cause_block = BasicBlock (), BasicBlock ()
1207+ builder .add (Branch (is_same_runtime , runtime_same_block , runtime_cause_block , Branch .BOOL ))
1208+
1209+ builder .activate_block (runtime_same_block )
1210+ reraise_original ()
1211+
1212+ builder .activate_block (runtime_cause_block )
1213+ is_stop = builder .binary_op (exc_type , stop_iteration , "is" , line )
1214+ cause_block , reraise_runtime_block = BasicBlock (), BasicBlock ()
1215+ builder .add (Branch (is_stop , cause_block , reraise_runtime_block , Branch .BOOL ))
1216+
1217+ builder .activate_block (cause_block )
1218+ cause = builder .py_get_attr (runtime_exc , "__cause__" , line )
1219+ is_cause = builder .binary_op (cause , builder .read (exc_value_target ), "is" , line )
1220+ cause_match_block , cause_miss_block = BasicBlock (), BasicBlock ()
1221+ builder .add (Branch (is_cause , cause_match_block , cause_miss_block , Branch .BOOL ))
1222+
1223+ builder .activate_block (cause_match_block )
1224+ reraise_original ()
1225+
1226+ builder .activate_block (cause_miss_block )
11621227 builder .call_c (reraise_exception_op , [], NO_TRACEBACK_LINE_NO )
11631228 builder .add (Unreachable ())
11641229
1165- builder .activate_block (stop_block )
1166- stop_exc = builder .call_c (get_exc_value_op , [], line )
1167- is_same_exc = builder .binary_op ( stop_exc , exc_original , "is" , line )
1230+ builder .activate_block (reraise_runtime_block )
1231+ builder .call_c (reraise_exception_op , [], NO_TRACEBACK_LINE_NO )
1232+ builder .add ( Unreachable () )
11681233
1169- suppress_block , reraise_block = BasicBlock (), BasicBlock ()
1170- builder .add (Branch (is_same_exc , reraise_block , suppress_block , Branch .BOOL ))
1234+ builder .activate_block (other_block )
1235+ other_exc = builder .call_c (get_exc_value_op , [], line )
1236+ is_same_other = builder .binary_op (other_exc , builder .read (exc_value_target ), "is" , line )
1237+ other_same_block , other_reraise_block = BasicBlock (), BasicBlock ()
1238+ builder .add (Branch (is_same_other , other_same_block , other_reraise_block , Branch .BOOL ))
11711239
1172- builder .activate_block (reraise_block )
1240+ builder .activate_block (other_same_block )
1241+ reraise_original ()
1242+
1243+ builder .activate_block (other_reraise_block )
11731244 builder .call_c (reraise_exception_op , [], NO_TRACEBACK_LINE_NO )
11741245 builder .add (Unreachable ())
11751246
@@ -1186,19 +1257,14 @@ def except_body() -> None:
11861257 # except StopIteration:
11871258 # pass
11881259 # else:
1189- # try:
1190- # raise RuntimeError("generator didn't stop")
1191- # finally:
1192- # gen.close()
1260+ # raise RuntimeError("generator didn't stop")
11931261
11941262 def else_body () -> None :
11951263 value = builder .call_c (next_raw_op , [builder .read (gen )], line )
1196- stop_block , close_block = BasicBlock (), BasicBlock ()
1197- builder .add (Branch (value , stop_block , close_block , Branch .IS_ERROR ))
1264+ stop_block , error_block = BasicBlock (), BasicBlock ()
1265+ builder .add (Branch (value , stop_block , error_block , Branch .IS_ERROR ))
11981266
1199- builder .activate_block (close_block )
1200- # TODO: this isn't exactly the right order
1201- builder .py_call (builder .py_get_attr (gen , "close" , line ), [], line )
1267+ builder .activate_block (error_block )
12021268 builder .add (
12031269 RaiseStandardError (RaiseStandardError .RUNTIME_ERROR , "generator didn't stop" , line )
12041270 )
0 commit comments