yield equivalent in C/JavaScript?
Bengt Richter
bokr at oz.net
Sun Jun 30 18:37:16 EDT 2002
On Sun, 30 Jun 2002 14:01:39 -0400, Oren Tirosh <oren-py-l at hishome.net> wrote:
>On Sat, Jun 29, 2002 at 07:12:46PM +0100, Robin Becker wrote:
>> Is there any way to do yielding easily in C? I have a bunch of programs
>> which are normally connected together using unix pipes. I would like to
>> merge them and the problem is then how to get them to communicate nicely
>> using a single process.
>
>It's possible to implement this in C using Duff's Device:
>
>#define BEGIN_GENERATOR static int _GenState=0; \
> switch(_GenState) { \
> case 0:
>
>#define END_GENERATOR } \
> _GenState = 0;
>
>#define YIELD(x) _GenState=__line__; return (x); case __line__:
>
>
>int generator(arguments) {
>
> static int foo, bar, etc; /* Make all variables static */
>
> BEGIN_GENERATOR
> for(...) {
> if(...) {
> ...
> YIELD(x)
> ...
> } else {
> ...
> }
> ...
> YIELD(y)
> ...
> }
> END_GENERATOR
>}
>
>If you want this to be reentrant use a struct passed as an argument
>to the function instead of static variables.
>
That's cool, but I'm wondering how generally BEGIN_GENERATOR's switch/case hopping
into the inside of the for loop like the above will work. Mind-bogglingly, it seems the
switch/case can slice just about orthogonally through loop code. Normally jumping into loops
is frowned upon, I thought, but it seems like case is practically like a label for a goto with
the minor restriction of being inside a switch(){...}, which your BEGIN_/END_GENERATOR guarantees.
I never explored this particular arena of possible abuses much ;-)
Anyway, you can't generate case numbers from line numbers without some risk of collision:
E.g., looking at the preprocessor output (which doesn't mind your ellipses ;-)
and putting a contrived switch around the second YIELD like
--
switch(y){
case 28:
YIELD(y);
printf("YIELD will make this case 29 here");
break;
case 29: printf("So this won't compile"); break;
}
--
in place of the plain YIELD(y) line, we get:
--
int generator(arguments) {
static int foo, bar, etc; /* Make all variables static */
static int _GenState=0; switch(_GenState) { case 0:
for(...) {
if(...) {
...
_GenState=21; return (x); case 21:
...
} else {
...
}
...
switch(y){
case 28:
_GenState=29; return (y); case 29:;
printf("YIELD will make this case 29 here");
break;
case 29: printf("So this won't compile"); break;
}
...
}
} _GenState = 0;
}
--
BTW, MSVCC6.0 wants
#define __line__ __LINE__
at the top to do the above. And for compiling, it doesn't like case __LINE__:
because __LINE__ appears not to be a constant expression to it. At the moment
I can't find the directive to get around that. It's happy to compile the
pre-processor output though ;-)
Regards,
Bengt Richter
More information about the Python-list
mailing list