-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Compiling Generators
Jukka Lehtosalo edited this page Oct 24, 2022
·
3 revisions
Generator functions must maintain state between invocations. A generator function is compiled into two classes. One is an environment class that maintains local variables of the function. The second one is the actual generator. The environment class is similar to what mypyc uses to support nested functions.
For example, consider this simple generator:
def f(x: int) -> Iterator[int]:
print('a')
yield x
print('b')
This is compiled to something roughly like this (in heavily simplified pseudo-python):
def f(x: int) -> Iterator[int]:
_env = f_env()
_env.x = x
_env.__mypyc_next_label__ = 0
_gen = f_gen()
_gen.__mypyc_env__ = _env
return _gen
class f_env:
x: int
__mypyc_next_label__: int
class f_gen:
__mypyc_env__: f_env
def __next__(self) -> int:
_env = self.__mypyc_env__
_label = _env.__mypyc_next_label__
if _label == 0:
print('a')
_ret = _env.x
_env.__mypyc_next_label__ = 1
return _ret
elif _label == 1:
print('b')
raise StopIteration()
The actual generated code is more complicated because of error handling, and close
/throw
/send
methods.