Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to implement Python yield functionality in freestanding C?

I recently came accross the yield keyword in Python (as well as JavaScript) - I understand that this is primarliy used for the generator pattern, but the language construct seems to be used in asynchronous functions as well where my interests lie. In asynchronous functions it may merely act as syntatic-sugar and I know there are alternative patterns to achieve the same effect - But I like it - A LOT!

I want to know if I can do something similar in C (even with inline assembly). I came across a Java implementation using threads https://github.com/mherrmann/java-generator-functions which I can more or less implement in C. However this is won't be a freestanding implementation, and my interest is purely in a freestanding implementation.

Coming to C co-routines (http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html), one of the deficits is that stack objects can't be used. However I am still OK with this since current asynchronous callback implementations also can't use the stack. However the problem lies in a freestanding implementation - I can't think of a way to collect all the register variables and store them without a hosted environment.

There's probably a solution using the setjmp/longjmp, however I am pretty sure these can't be implemented freestanding.

So the question is: Is it possible to implement Python yield functionality in freestanding C?

Personally I think I have exhausted the possibilites, so I'll ask this - If you could have a hosted implementation, how would you implement it (preferably with some macro magic)? I have a fairly ugly implementation which I'll post later on if nothing cool comes up.

Also I don't want C++ implementations - Unless you can wrap around the C++ with pure C functions.

EDIT: A basic requirement is that the generator function has to be re-enterant.

like image 576
tinkerbeast Avatar asked May 22 '15 14:05

tinkerbeast


People also ask

How does Python implement yield?

yield in Python can be used like the return statement in a function. When done so, the function instead of returning the output, it returns a generator that can be iterated upon. You can then iterate through the generator to extract items. Iterating is done using a for loop or simply using the next() function.

Which type of Python function contains a yield statement?

yield keyword is used to create a generator function. A type of function that is memory efficient and can be used like an iterator object. In layman terms, the yield keyword will turn any expression that is given with it into a generator object and return it to the caller.

Does yield stop execution Python?

Inside a program, when you call a function that has a yield statement, as soon as a yield is encountered, the execution of the function stops and returns an object of the generator to the function caller.

How do you use yield instead of return in Python?

Yield is generally used to convert a regular Python function into a generator. Return is generally used for the end of the execution and “returns” the result to the caller statement. It replace the return of a function to suspend its execution without destroying local variables.


1 Answers

I'm going to answer using setjmp and longjmp since those interfaces are standard and you can easily find their implementations for any HW platform. They are freestanding, but HW dependent.

struct _yield_state {
    jmp_buf buf;
    _Bool yielded;
};

#define yieldable  static struct _yield_state _state; \
                   if (_state.yielded) longjmp(_state.buf, 1); else {}


#define yield(x)  if (setjmp(_state.buf)) { _state.yielded = false;          }\
                  else                    { _state.yielded = true;  return x }

int func(int a, int b)
{
    yieldable;

    if (a > b)
        yield(0);

    return a + b;
}

You can find an example setjmp and longjmp implementation here. It is pure assembly, specific only to the underlying hardware.

like image 139
mtijanic Avatar answered Sep 28 '22 18:09

mtijanic