Skip to content

Commit bf38e2a

Browse files
committed
Implement send() method for generators.
1 parent 56bb636 commit bf38e2a

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

py/objgenerator.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,15 @@ mp_obj_t gen_instance_getiter(mp_obj_t self_in) {
7373
return self_in;
7474
}
7575

76-
mp_obj_t gen_instance_iternext(mp_obj_t self_in) {
76+
static mp_obj_t gen_send(mp_obj_t self_in, mp_obj_t send_value) {
7777
mp_obj_gen_instance_t *self = self_in;
78+
if (self->sp == self->state - 1) {
79+
if (send_value != mp_const_none) {
80+
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "can't send non-None value to a just-started generator"));
81+
}
82+
} else {
83+
*self->sp = send_value;
84+
}
7885
bool yield = mp_execute_byte_code_2(self->code_info, &self->ip, &self->state[self->n_state - 1], &self->sp);
7986
if (yield) {
8087
return *self->sp;
@@ -87,13 +94,24 @@ mp_obj_t gen_instance_iternext(mp_obj_t self_in) {
8794
}
8895
}
8996
}
97+
static MP_DEFINE_CONST_FUN_OBJ_2(gen_send_obj, gen_send);
98+
99+
mp_obj_t gen_instance_iternext(mp_obj_t self_in) {
100+
return gen_send(self_in, mp_const_none);
101+
}
102+
103+
static const mp_method_t gen_type_methods[] = {
104+
{ "send", &gen_send_obj },
105+
{ NULL, NULL }, // end-of-list sentinel
106+
};
90107

91108
const mp_obj_type_t gen_instance_type = {
92109
{ &mp_const_type },
93110
"generator",
94111
.print = gen_instance_print,
95112
.getiter = gen_instance_getiter,
96113
.iternext = gen_instance_iternext,
114+
.methods = gen_type_methods,
97115
};
98116

99117
mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args) {

py/vm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_arg
7373

7474
// fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
7575
// sp points to bottom of stack which grows up
76+
// returns true if bytecode yielded
7677
bool mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out) {
7778
// careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think)
7879

tests/basics/generator_send.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
def f():
2+
n = 0
3+
while True:
4+
n = yield n + 1
5+
print(n)
6+
7+
g = f()
8+
try:
9+
g.send(1)
10+
except TypeError:
11+
print("caught")
12+
13+
print(g.send(None))
14+
print(g.send(100))
15+
print(g.send(200))

0 commit comments

Comments
 (0)