8000 py: Fix generator where state array was incorrectly indexed. · micropython/micropython@0ff8839 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0ff8839

Browse files
committed
py: Fix generator where state array was incorrectly indexed.
Generator objects now allocate the object and the state in one malloc. This improvement fixes Issue #38.
1 parent ebd2e87 commit 0ff8839

File tree

3 files changed

+26
-26
lines changed

3 files changed

+26
-26
lines changed

py/obj.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ mp_obj_t mp_obj_new_range_iterator(int cur, int stop, int step);
136136
mp_obj_t mp_obj_new_fun_bc(int n_args, uint n_state, const byte *code);
137137
mp_obj_t mp_obj_new_fun_asm(uint n_args, void *fun);
138138
mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_stack, mp_obj_t fun);
139-
mp_obj_t mp_obj_new_gen_instance(mp_obj_t state, const byte *ip, mp_obj_t *sp);
139+
mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args);
140140
mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple);
141141
mp_obj_t mp_obj_new_tuple(uint n, mp_obj_t *items);
142142
mp_obj_t mp_obj_new_tuple_reverse(uint n, mp_obj_t *items);

py/objgenerator.c

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
typedef struct _mp_obj_gen_wrap_t {
1717
mp_obj_base_t base;
18-
int n_state;
18+
uint n_state;
1919
mp_obj_t *fun;
2020
} mp_obj_gen_wrap_t;
2121

@@ -31,22 +31,8 @@ mp_obj_t gen_wrap_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
3131
if (n_args != bc_n_args) {
3232
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)bc_n_args, (const char*)(machine_int_t)n_args));
3333
}
34-
mp_obj_t *state = m_new(mp_obj_t, 1 + self->n_state);
35-
// put function object at first slot in state (to keep u_gen_instance small)
36-
state[0] = self_fun;
37-
// init args
38-
for (int i = 0; i < n_args; i++) {
39-
state[1 + i] = args[n_args - 1 - i];
40-
}
4134

42-
// TODO
43-
// prelude for making cells (closed over variables)
44-
// for now we just make sure there are no cells variables
45-
// need to work out how to implement closed over variables in generators
46-
assert(bc_code[0] == 0);
47-
bc_code += 1;
48-
49-
return mp_obj_new_gen_instance(state, bc_code, state + self->n_state);
35+
return mp_obj_new_gen_instance(bc_code, self->n_state, n_args, args);
5036
}
5137

5238
const mp_obj_type_t gen_wrap_type = {
@@ -75,9 +61,9 @@ mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_stack, mp_obj_t fun) {
7561

7662
typedef struct _mp_obj_gen_instance_t {
7763
mp_obj_base_t base;
78-
mp_obj_t *state;
7964
const byte *ip;
8065
mp_obj_t *sp;
66+
mp_obj_t state[];
8167
} mp_obj_gen_instance_t;
8268

8369
void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
@@ -90,9 +76,7 @@ mp_obj_t gen_instance_getiter(mp_obj_t self_in) {
9076

9177
mp_obj_t gen_instance_iternext(mp_obj_t self_in) {
9278
mp_obj_gen_instance_t *self = self_in;
93-
//mp_obj_base_t *fun = self->u_gen_instance.state[0];
94-
//assert(fun->kind == O_FUN_BC);
95-
bool yield = mp_execute_byte_code_2(&self->ip, &self->state[1], &self->sp);
79+
bool yield = mp_execute_byte_code_2(&self->ip, &self->state[0], &self->sp);
9680
if (yield) {
9781
return *self->sp;
9882
} else {
@@ -117,11 +101,24 @@ const mp_obj_type_t gen_instance_type = {
117101
{{NULL, NULL},}, // method list
118102
};
119103

120-
mp_obj_t mp_obj_new_gen_instance(mp_obj_t state, const byte *ip, mp_obj_t *sp) {
121-
mp_obj_gen_instance_t *o = m_new_obj(mp_obj_gen_instance_t);
104+
// args are in reverse order in the array
105+
mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args) {
106+
mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, mp_obj_t, n_state);
122107
o->base.type = &gen_instance_type;
123-
o->state = state;
124-
o->ip = ip;
125-
o->sp = sp;
108+
o->ip = bytecode;
109+
o->sp = o->state + n_state;
110+
111+
// copy args (which are in reverse order) to start of state array
112+
for (int i = 0; i < n_args; i++) {
113+
o->state[i] = args[n_args - 1 - i];
114+
}
115+
116+
// TODO
117+
// prelude for making cells (closed over variables)
118+
// for now we just make sure there are no cells variables
119+
// need to work out how to implement closed over variables in generators
120+
assert(o->ip[0] == 0);
121+
o->ip += 1;
122+
126123
return o;
127124
}

tests/basics/tests/generator2.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
gen = (i for i in range(10))
2+
for i in gen:
3+
print(i)

0 commit comments

Comments
 (0)
0