-
Notifications
You must be signed in to change notification settings - Fork 1
/
is_gen.py
75 lines (57 loc) · 2.02 KB
/
is_gen.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from utils import overloadmethod, ApeInternalError
from astpass import DeepAstPass
import cstnodes as E
class Sentinel:
def __init__(self, value):
self.value = value
def __repr__(self):
return f'Sentinel({self.value!r})'
def is_sentinel(x):
return isinstance(x, Sentinel)
def is_iterable(x):
try:
iter(x)
return True
except TypeError:
return False
class IsGenPass(DeepAstPass):
"""A compiler pass to test for the presence of generators"""
def true_args(self, args):
return any(self.true_arg(a) for a in args if a is not args and (is_iterable(a) or is_sentinel(a)))
def true_arg(self, arg):
if is_iterable(arg):
return self.true_args(arg)
if is_sentinel(arg):
return arg.value
raise ApeInternalError('We should\'t ever get here')
def override_do_visit_wrapper(self, ast, new):
if isinstance(new, Sentinel):
return new
if isinstance(new, bool):
return Sentinel(new)
# no atomic expressions can yield
if ast is new:
return Sentinel(False)
cls, args = new
try:
return Sentinel(self.true_args(args))
except TypeError:
raise
def visit(self, ast):
return self.my_visit(ast)
@overloadmethod(use_as_default=True)
def my_visit(self, ast):
return super().visit(ast)
@my_visit.on((E.YieldFromExpression, E.YieldExpression))
def my_visit_Yield_Or_YieldFrom_Expression(self, ast):
return Sentinel(True)
@my_visit.on((E.FunctionExpression, E.FunctionDefinition))
def my_visit_FunctionDefinition_Or_FunctionExpression(self, ast):
return Sentinel(any(self.is_gen(p.default) for p in ast.params if p.default is not None))
@my_visit.wrapper()
def my_visit_wrapper(self, ast, new):
return self.override_do_visit_wrapper(ast, new)
def is_gen(self, ast):
return self.visit(ast).value
def is_gen(ast):
return IsGenPass().is_gen(ast)