@@ -73,8 +73,11 @@ mp_obj_t gen_instance_getiter(mp_obj_t self_in) {
7373 return self_in ;
7474}
7575
76- static mp_obj_t gen_send (mp_obj_t self_in , mp_obj_t send_value ) {
76+ static mp_obj_t gen_next_send (mp_obj_t self_in , mp_obj_t send_value ) {
7777 mp_obj_gen_instance_t * self = self_in ;
78+ if (self -> ip == 0 ) {
79+ return mp_const_stop_iteration ;
80+ }
7881 if (self -> sp == self -> state - 1 ) {
7982 if (send_value != mp_const_none ) {
8083 nlr_jump (mp_obj_new_exception_msg (MP_QSTR_TypeError , "can't send non-None value to a just-started generator" ));
@@ -86,6 +89,12 @@ static mp_obj_t gen_send(mp_obj_t self_in, mp_obj_t send_value) {
8689 if (yield ) {
8790 return * self -> sp ;
8891 } else {
92+ // Explicitly mark generator as completed. If we don't do this,
93+ // subsequent next() may re-execute statements after last yield
94+ // again and again, leading to side effects.
95+ // TODO: check how return with value behaves under such conditions
96+ // in CPython.
97+ self -> ip = 0 ;
8998 if (* self -> sp == mp_const_none ) {
9099 return mp_const_stop_iteration ;
91100 } else {
@@ -94,14 +103,22 @@ static mp_obj_t gen_send(mp_obj_t self_in, mp_obj_t send_value) {
94103 }
95104 }
96105}
97- static MP_DEFINE_CONST_FUN_OBJ_2 (gen_send_obj , gen_send ) ;
98106
99107mp_obj_t gen_instance_iternext (mp_obj_t self_in ) {
100- return gen_send (self_in , mp_const_none );
108+ return gen_next_send (self_in , mp_const_none );
109+ }
110+
111+ static mp_obj_t gen_instance_send (mp_obj_t self_in , mp_obj_t send_value ) {
112+ mp_obj_t ret = gen_next_send (self_in , send_value );
113+ if (ret == mp_const_stop_iteration ) {
114+ nlr_jump (mp_obj_new_exception (MP_QSTR_StopIteration ));
115+ }
116+ return ret ;
101117}
118+ static MP_DEFINE_CONST_FUN_OBJ_2 (gen_instance_send_obj , gen_instance_send ) ;
102119
103120static const mp_method_t gen_type_methods [] = {
104- { "send" , & gen_send_obj },
121+ { "send" , & gen_instance_send_obj },
105122 { NULL , NULL }, // end-of-list sentinel
106123};
107124
0 commit comments