@@ -9,6 +9,7 @@ use crate::exceptions::{self, ExceptionCtor, PyBaseExceptionRef};
99use crate :: function:: { single_or_tuple_any, PyFuncArgs } ;
1010use crate :: obj:: objbool;
1111use crate :: obj:: objcode:: PyCodeRef ;
12+ use crate :: obj:: objcoroinner:: Coro ;
1213use crate :: obj:: objcoroutine:: PyCoroutine ;
1314use crate :: obj:: objdict:: { PyDict , PyDictRef } ;
1415use crate :: obj:: objgenerator:: PyGenerator ;
@@ -205,23 +206,34 @@ impl Frame {
205206 }
206207 }
207208
209+ pub fn yield_from_target ( & self ) -> Option < PyObjectRef > {
210+ if let Some ( bytecode:: Instruction :: YieldFrom ) = self . code . instructions . get ( self . lasti . get ( ) )
211+ {
212+ Some ( self . last_value ( ) )
213+ } else {
214+ None
215+ }
216+ }
217+
208218 pub ( crate ) fn gen_throw (
209219 & self ,
210220 vm : & VirtualMachine ,
211221 exc_type : PyObjectRef ,
212222 exc_val : PyObjectRef ,
213223 exc_tb : PyObjectRef ,
214224 ) -> PyResult < ExecutionResult > {
215- if let bytecode:: Instruction :: YieldFrom = self . code . instructions [ self . lasti . get ( ) ] {
216- let coro = self . last_value ( ) ;
217- vm. call_method ( & coro, "throw" , vec ! [ exc_type, exc_val, exc_tb] )
218- . or_else ( |err| {
219- self . pop_value ( ) ;
220- self . lasti . set ( self . lasti . get ( ) + 1 ) ;
221- let val = objiter:: stop_iter_value ( vm, & err) ?;
222- self . _send ( coro, val, vm)
223- } )
224- . map ( ExecutionResult :: Yield )
225+ if let Some ( coro) = self . yield_from_target ( ) {
226+ let res = match self . builtin_coro ( & coro) {
227+ Some ( coro) => coro. throw ( exc_type, exc_val, exc_tb, vm) ,
228+ None => vm. call_method ( & coro, "throw" , vec ! [ exc_type, exc_val, exc_tb] ) ,
229+ } ;
230+ res. or_else ( |err| {
231+ self . pop_value ( ) ;
232+ self . lasti . set ( self . lasti . get ( ) + 1 ) ;
233+ let val = objiter:: stop_iter_value ( vm, & err) ?;
234+ self . _send ( coro, val, vm)
235+ } )
236+ . map ( ExecutionResult :: Yield )
225237 } else {
226238 let exception = exceptions:: normalize ( exc_type, exc_val, exc_tb, vm) ?;
227239 match self . unwind_blocks ( vm, UnwindReason :: Raising { exception } ) {
@@ -1009,13 +1021,16 @@ impl Frame {
10091021 Err ( exception)
10101022 }
10111023
1012- fn _send ( & self , coro : PyObjectRef , val : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
1013- let builtin_coro = match_class ! ( match coro {
1024+ fn builtin_coro < ' a > ( & self , coro : & ' a PyObjectRef ) -> Option < & ' a Coro > {
1025+ match_class ! ( match coro {
10141026 ref g @ PyGenerator => Some ( g. as_coro( ) ) ,
10151027 ref c @ PyCoroutine => Some ( c. as_coro( ) ) ,
10161028 _ => None ,
1017- } ) ;
1018- match builtin_coro {
1029+ } )
1030+ }
1031+
1032+ fn _send ( & self , coro : PyObjectRef , val : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
1033+ match self . builtin_coro ( & coro) {
10191034 Some ( coro) => coro. send ( val, vm) ,
10201035 None if vm. is_none ( & val) => objiter:: call_next ( vm, & coro) ,
10211036 None => vm. call_method ( & coro, "send" , vec ! [ val] ) ,
0 commit comments