2010/12/5 Stefan Behnel <[email protected]>:
> Hi,
>
> I just noticed that Vitja's closure refactoring brought us closer to
> supporting generator expressions (before supporting generators and
> coroutines). Here's what's missing:
>
> 1) transform a GeneratorExpressionNode into a DefNode or a subclass
> (obviously excluding inlined generator expressions)
>
> 2) generate the resume code at the start of the function body
>
> 3) store temps in closures. For simplicity, this can be done with a tuple
> (which supports NULL values to a certain extent). That way, we do not need
> to declare each temp separately as a closure field. The remaining tricky
> bit is then to figure out the maximum number of temps that are alive at a
> YieldExprNode (ok, that's actually easy) and to pass that number on to the
> closure class that needs to allocate a sufficiently large tuple.
>
> That doesn't sound too hard.
>
> The generators CEP has the details for each step.
>
> http://wiki.cython.org/enhancements/generators
>
> Going for generator expressions before implementing generators has the
> advantage that it gives us most of the infrastructure without requiring the
> additional steps of passing initial arguments into the generator and
> implementing the complete coroutine protocol (the yield nodes cannot return
> values, for example).
>
> Anyone with a little time to spare?
>
> Stefan
> _______________________________________________
> Cython-dev mailing list
> [email protected]
> http://codespeak.net/mailman/listinfo/cython-dev
>
Hi!
I've started woring on generators on friday.
Now it can generate some code, but it doesn't work yet, what is done:
- switch() for resuming and argument parsing
- yield stuff
- closure temp allocation
I'm going to put all the generator stuff into closure
Generator function:
Creates closure with all temps, args, variables, and all the internal stuff:
Also closure have all the required generator methods __iter__(),
__nextiter__() and so on.
def my_generator(self, args, kwargs):
closure = my_generator_closure_new()
closure.is_running = 0
closure.resume_label = 0
closure.args = args
closure.kwargs = kwargs
closure.outer_scope = self
closure.generator_body = my_generator_body
return closure
generator body:
def my_generator_body(closure, value, is_exception):
# switch case
switch (closure.resume_lable):
case 0:
goto parse_arguments;
case 1:
goto resume_from_yield1;
parse_arguments:
# function body here
About temps:
now temps are allocated in closure using declare_var() and it works fine.
I'm not sure about manage_ref flag I guess that temps with
manage_ref=False shouldn't be allocated on closure (am I right?)
I'm not sure that tuple should be better for temps.
TODO:
- create C function that returns closure
- generator utility code
I have problem with closures and generators.
Now I want to implement closure structure this way:
struct abstract_generator {
PY_OBJECT_HEAD
/* generator internal vars */
PyObject *(*body)(struct closure *, PyObject *, int);
int resume_label;
}
struct closure {
/* abstract_generator */
PY_OBJECT_HEAD
/* generator internal vars */
PyObject *(*body)(struct closure *, PyObject *, int);
int resume_label;
,,,,
/* Closure stuff */
} ;
and generator utility function will work like this:
PyObject *abstract_generator_next(PyObject *self, PyObject *args)
{
struct abstract_generator *generator = (struct abstract_generator *) self;
PyObject *retval;
// check running
retval = generator->body(self, None, 0);
// unlock running
return retval;
}
But this way should be much better, don't know if that is possible btw.
struct closure {
struct abstract_generator generator;
/* closure stuff here */
...
} ;
I add MarkGenerator visitor, that sets is_generator flag on DefNode
and checks for returns/yields.
Then CreateClosureClasses will create correct closure class for generator.
--
vitja.
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev