-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfree_vars.py
95 lines (75 loc) · 2.9 KB
/
free_vars.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#merges a list of sets into one set
def combine_set_list(set_list):
#reduce is python's foldLeft function
return reduce(lambda a,b: a | b, set_list, set([]))
def free_vars_stmt(stmt):
fv = set([])
bv = set([])
for n in stmt.nodes:
#In a statement, we need to keep track of the bound variables,
#rather than just excluding them from the exp's free var list.
if isinstance(n, Assign):
fv = fv | free_vars(n.expr)
for ass_node in n.nodes:
bv = bv | set([ass_node.name])
elif isinstance(n, Lambda) or isinstance(n,Function):
fv = fv | free_vars(n.code)
bv = bv | set(n.argnames)
else:
fv = fv | free_vars(n)
return fv - bv
def free_vars(n):
if isinstance(n, Module):
return free_vars(n.node)
#This should always return an empty set. (Useful for debug?)
if isinstance(n,Stmt):
return free_vars_stmt(n)
if isinstance(n, Const):
return (set([]))
elif isinstance(n, Name):
if n.name == 'True' or n.name == 'False':
return set([])
else:
return set([n.name])
elif isinstance(n, Printnl):
printd('In Printnl path')
return free_vars(n.nodes[0])
elif isinstance(n, UnarySub):
return free_vars(n.expr)
elif isinstance(n, Add):
return free_vars(n.left) | free_vars(n.right)
elif isinstance(n, Discard):
return free_vars(n.expr)
elif isinstance(n, CallFunc):
fv_args = [free_vars(e) for e in n.args]
free_in_args = combine_set_list(fv_args)
return (free_vars(n.node) | free_in_args) - set(['input'])
#special casing input for the moment.
elif isinstance(n, Assign):
return free_vars(n.expr) - set(n.nodes)
elif isinstance(n, Compare):
return free_vars(n.expr) | free_vars(n.ops[0][1])
elif isinstance(n, Or) or isinstance(n, And):
fv = [free_vars(e) for e in n.nodes]
return combine_set_list(fv)
elif isinstance(n, Not):
return free_vars(n.expr)
elif isinstance(n, List):
fv = [free_vars(e) for e in n.nodes]
return combine_set_list(fv)
elif isinstance(n, Dict):
fv = [ free_vars(k) | free_vars(v) for (k, v) in n.items]
return combine_set_list(fv)
elif isinstance(n, Subscript):
fv = [free_vars(sub) for sub in n.subs]
return combine_set_list(fv) | free_vars(n.expr)
elif isinstance(n, IfExp):
return free_vars(n.test) | free_vars(n.then) | free_vars(n.else_)
#Function declarations
elif isinstance(n, Lambda) or isinstance(n,Function):
return free_vars(n.code) - set(n.argnames)
#n.code is an expression w/ Lambda and a Stmt with Func
elif isinstance(n, Return):
return free_vars(n.value)
else:
return set([])