@@ -227,19 +227,25 @@ static int codegen_call_helper(compiler *c, location loc,
227227static int codegen_try_except (compiler * , stmt_ty );
228228static int codegen_try_star_except (compiler * , stmt_ty );
229229
230+ typedef enum {
231+ ITERABLE_IN_LOCAL = 0 ,
232+ ITERABLE_ON_STACK = 1 ,
233+ ITERATOR_ON_STACK = 2 ,
234+ } IterStackPosition ;
235+
230236static int codegen_sync_comprehension_generator (
231237 compiler * c , location loc ,
232238 asdl_comprehension_seq * generators , int gen_index ,
233239 int depth ,
234240 expr_ty elt , expr_ty val , int type ,
235- int iter_on_stack );
241+ IterStackPosition iter_pos );
236242
237243static int codegen_async_comprehension_generator (
238244 compiler * c , location loc ,
239245 asdl_comprehension_seq * generators , int gen_index ,
240246 int depth ,
241247 expr_ty elt , expr_ty val , int type ,
242- int iter_on_stack );
248+ IterStackPosition iter_pos );
243249
244250static int codegen_pattern (compiler * , pattern_ty , pattern_context * );
245251static int codegen_match (compiler * , stmt_ty );
@@ -665,6 +671,18 @@ codegen_enter_scope(compiler *c, identifier name, int scope_type,
665671 if (scope_type == COMPILE_SCOPE_MODULE ) {
666672 loc .lineno = 0 ;
667673 }
674+ /* Add the generator prefix instructions. */
675+
676+ PySTEntryObject * ste = SYMTABLE_ENTRY (c );
677+ if (ste -> ste_coroutine || ste -> ste_generator ) {
678+ /* Note that RETURN_GENERATOR + POP_TOP have a net stack effect
679+ * of 0. This is because RETURN_GENERATOR pushes the generator
680+ before returning. */
681+ location loc = LOCATION (lineno , lineno , -1 , -1 );
682+ ADDOP (c , loc , RETURN_GENERATOR );
683+ ADDOP (c , loc , POP_TOP );
684+ }
685+
668686 ADDOP_I (c , loc , RESUME , RESUME_AT_FUNC_START );
669687 if (scope_type == COMPILE_SCOPE_MODULE ) {
670688 ADDOP (c , loc , ANNOTATIONS_PLACEHOLDER );
@@ -1187,10 +1205,15 @@ codegen_wrap_in_stopiteration_handler(compiler *c)
11871205{
11881206 NEW_JUMP_TARGET_LABEL (c , handler );
11891207
1190- /* Insert SETUP_CLEANUP at start */
1208+ /* Insert SETUP_CLEANUP just before RESUME */
1209+ instr_sequence * seq = INSTR_SEQUENCE (c );
1210+ int resume = 0 ;
1211+ while (_PyInstructionSequence_GetInstruction (seq , resume ).i_opcode != RESUME ) {
1212+ resume ++ ;
1213+ }
11911214 RETURN_IF_ERROR (
11921215 _PyInstructionSequence_InsertInstruction (
1193- INSTR_SEQUENCE ( c ), 0 ,
1216+ seq , resume ,
11941217 SETUP_CLEANUP , handler .id , NO_LOCATION ));
11951218
11961219 ADDOP_LOAD_CONST (c , NO_LOCATION , Py_None );
@@ -4401,18 +4424,18 @@ codegen_comprehension_generator(compiler *c, location loc,
44014424 asdl_comprehension_seq * generators , int gen_index ,
44024425 int depth ,
44034426 expr_ty elt , expr_ty val , int type ,
4404- int iter_on_stack )
4427+ IterStackPosition iter_pos )
44054428{
44064429 comprehension_ty gen ;
44074430 gen = (comprehension_ty )asdl_seq_GET (generators , gen_index );
44084431 if (gen -> is_async ) {
44094432 return codegen_async_comprehension_generator (
44104433 c , loc , generators , gen_index , depth , elt , val , type ,
4411- iter_on_stack );
4434+ iter_pos );
44124435 } else {
44134436 return codegen_sync_comprehension_generator (
44144437 c , loc , generators , gen_index , depth , elt , val , type ,
4415- iter_on_stack );
4438+ iter_pos );
44164439 }
44174440}
44184441
@@ -4421,7 +4444,7 @@ codegen_sync_comprehension_generator(compiler *c, location loc,
44214444 asdl_comprehension_seq * generators ,
44224445 int gen_index , int depth ,
44234446 expr_ty elt , expr_ty val , int type ,
4424- int iter_on_stack )
4447+ IterStackPosition iter_pos )
44254448{
44264449 /* generate code for the iterator, then each of the ifs,
44274450 and then write to the element */
@@ -4433,7 +4456,7 @@ codegen_sync_comprehension_generator(compiler *c, location loc,
44334456 comprehension_ty gen = (comprehension_ty )asdl_seq_GET (generators ,
44344457 gen_index );
44354458
4436- if (! iter_on_stack ) {
4459+ if (iter_pos == ITERABLE_IN_LOCAL ) {
44374460 if (gen_index == 0 ) {
44384461 assert (METADATA (c )-> u_argcount == 1 );
44394462 ADDOP_I (c , loc , LOAD_FAST , 0 );
@@ -4468,9 +4491,12 @@ codegen_sync_comprehension_generator(compiler *c, location loc,
44684491 }
44694492
44704493 if (IS_JUMP_TARGET_LABEL (start )) {
4471- depth += 2 ;
4472- ADDOP (c , LOC (gen -> iter ), GET_ITER );
4494+ if (iter_pos != ITERATOR_ON_STACK ) {
4495+ ADDOP (c , LOC (gen -> iter ), GET_ITER );
4496+ depth += 1 ;
4497+ }
44734498 USE_LABEL (c , start );
4499+ depth += 1 ;
44744500 ADDOP_JUMP (c , LOC (gen -> iter ), FOR_ITER , anchor );
44754501 }
44764502 VISIT (c , expr , gen -> target );
@@ -4486,7 +4512,7 @@ codegen_sync_comprehension_generator(compiler *c, location loc,
44864512 RETURN_IF_ERROR (
44874513 codegen_comprehension_generator (c , loc ,
44884514 generators , gen_index , depth ,
4489- elt , val , type , 0 ));
4515+ elt , val , type , ITERABLE_IN_LOCAL ));
44904516 }
44914517
44924518 location elt_loc = LOC (elt );
@@ -4545,7 +4571,7 @@ codegen_async_comprehension_generator(compiler *c, location loc,
45454571 asdl_comprehension_seq * generators ,
45464572 int gen_index , int depth ,
45474573 expr_ty elt , expr_ty val , int type ,
4548- int iter_on_stack )
4574+ IterStackPosition iter_pos )
45494575{
45504576 NEW_JUMP_TARGET_LABEL (c , start );
45514577 NEW_JUMP_TARGET_LABEL (c , send );
@@ -4555,7 +4581,7 @@ codegen_async_comprehension_generator(compiler *c, location loc,
45554581 comprehension_ty gen = (comprehension_ty )asdl_seq_GET (generators ,
45564582 gen_index );
45574583
4558- if (! iter_on_stack ) {
4584+ if (iter_pos == ITERABLE_IN_LOCAL ) {
45594585 if (gen_index == 0 ) {
45604586 assert (METADATA (c )-> u_argcount == 1 );
45614587 ADDOP_I (c , loc , LOAD_FAST , 0 );
@@ -4565,7 +4591,9 @@ codegen_async_comprehension_generator(compiler *c, location loc,
45654591 VISIT (c , expr , gen -> iter );
45664592 }
45674593 }
4568- ADDOP (c , LOC (gen -> iter ), GET_AITER );
4594+ if (iter_pos != ITERATOR_ON_STACK ) {
4595+ ADDOP (c , LOC (gen -> iter ), GET_AITER );
4596+ }
45694597
45704598 USE_LABEL (c , start );
45714599 /* Runtime will push a block here, so we need to account for that */
@@ -4795,11 +4823,13 @@ codegen_comprehension(compiler *c, expr_ty e, int type,
47954823 location loc = LOC (e );
47964824
47974825 outermost = (comprehension_ty ) asdl_seq_GET (generators , 0 );
4826+ IterStackPosition iter_state ;
47984827 if (is_inlined ) {
47994828 VISIT (c , expr , outermost -> iter );
48004829 if (push_inlined_comprehension_state (c , loc , entry , & inline_state )) {
48014830 goto error ;
48024831 }
4832+ iter_state = ITERABLE_ON_STACK ;
48034833 }
48044834 else {
48054835 /* Receive outermost iter as an implicit argument */
@@ -4810,6 +4840,23 @@ codegen_comprehension(compiler *c, expr_ty e, int type,
48104840 (void * )e , e -> lineno , NULL , & umd ) < 0 ) {
48114841 goto error ;
48124842 }
4843+ if (type == COMP_GENEXP ) {
4844+ /* Insert GET_ITER before RETURN_GENERATOR.
4845+ https://docs.python.org/3/reference/expressions.html#generator-expressions */
4846+ RETURN_IF_ERROR (
4847+ _PyInstructionSequence_InsertInstruction (
4848+ INSTR_SEQUENCE (c ), 0 ,
4849+ LOAD_FAST , 0 , LOC (outermost -> iter )));
4850+ RETURN_IF_ERROR (
4851+ _PyInstructionSequence_InsertInstruction (
4852+ INSTR_SEQUENCE (c ), 1 ,
4853+ outermost -> is_async ? GET_AITER : GET_ITER ,
4854+ 0 , LOC (outermost -> iter )));
4855+ iter_state = ITERATOR_ON_STACK ;
4856+ }
4857+ else {
4858+ iter_state = ITERABLE_IN_LOCAL ;
4859+ }
48134860 }
48144861 Py_CLEAR (entry );
48154862
@@ -4836,9 +4883,8 @@ codegen_comprehension(compiler *c, expr_ty e, int type,
48364883 ADDOP_I (c , loc , SWAP , 2 );
48374884 }
48384885 }
4839-
48404886 if (codegen_comprehension_generator (c , loc , generators , 0 , 0 ,
4841- elt , val , type , is_inlined ) < 0 ) {
4887+ elt , val , type , iter_state ) < 0 ) {
48424888 goto error_in_scope ;
48434889 }
48444890
0 commit comments