blob: a58be007b8c1031e9588f7d6f01dff3f91abc051 [file] [log] [blame]
Jeremy Hylton4588c782001-01-25 20:11:23 +00001from test.test_support import verify, TestFailed
2
3print "1. simple nesting"
4
5def make_adder(x):
6 def adder(y):
7 return x + y
8 return adder
9
10inc = make_adder(1)
11plus10 = make_adder(10)
12
13verify(inc(1) == 2)
14verify(plus10(-2) == 8)
15
16print "2. extra nesting"
17
18def make_adder2(x):
19 def extra(): # check freevars passing through non-use scopes
20 def adder(y):
21 return x + y
22 return adder
23 return extra()
24
25inc = make_adder2(1)
26plus10 = make_adder2(10)
27
28verify(inc(1) == 2)
29verify(plus10(-2) == 8)
30
31print "3. simple nesting + rebinding"
32
33def make_adder3(x):
34 def adder(y):
35 return x + y
36 x = x + 1 # check tracking of assignment to x in defining scope
37 return adder
38
39inc = make_adder3(0)
40plus10 = make_adder3(9)
41
42verify(inc(1) == 2)
43verify(plus10(-2) == 8)
44
45print "4. nesting with global but no free"
46
47def make_adder4(): # XXX add exta level of indirection
48 def nest():
49 def nest():
50 def adder(y):
51 return global_x + y # check that plain old globals work
52 return adder
53 return nest()
54 return nest()
55
56global_x = 1
57adder = make_adder4()
58verify(adder(1) == 2)
59
60global_x = 10
61verify(adder(-2) == 8)
62
63print "5. nesting through class"
64
65def make_adder5(x):
66 class Adder:
67 def __call__(self, y):
68 return x + y
69 return Adder()
70
71inc = make_adder5(1)
72plus10 = make_adder5(10)
73
74verify(inc(1) == 2)
75verify(plus10(-2) == 8)
76
77print "6. nesting plus free ref to global"
78
79def make_adder6(x):
80 global global_nest_x
81 def adder(y):
82 return global_nest_x + y
83 global_nest_x = x
84 return adder
85
86inc = make_adder6(1)
87plus10 = make_adder6(10)
88
Jeremy Hylton251ef962001-01-30 01:26:53 +000089verify(inc(1) == 11) # there's only one global
Jeremy Hylton4588c782001-01-25 20:11:23 +000090verify(plus10(-2) == 8)
91
92print "7. nearest enclosing scope"
93
94def f(x):
95 def g(y):
96 x = 42 # check that this masks binding in f()
97 def h(z):
98 return x + z
99 return h
100 return g(2)
101
102test_func = f(10)
103verify(test_func(5) == 47)
104
105print "8. mixed freevars and cellvars"
106
107def identity(x):
Tim Peters10fb3862001-02-09 20:17:14 +0000108 return x
Jeremy Hylton4588c782001-01-25 20:11:23 +0000109
110def f(x, y, z):
111 def g(a, b, c):
112 a = a + x # 3
113 def h():
Tim Peters10fb3862001-02-09 20:17:14 +0000114 # z * (4 + 9)
115 # 3 * 13
Jeremy Hylton4588c782001-01-25 20:11:23 +0000116 return identity(z * (b + y))
117 y = c + z # 9
118 return h
119 return g
120
121g = f(1, 2, 3)
122h = g(2, 4, 6)
Tim Peters10fb3862001-02-09 20:17:14 +0000123verify(h() == 39)
Jeremy Hylton4588c782001-01-25 20:11:23 +0000124
125print "9. free variable in method"
126
127def test():
128 method_and_var = "var"
129 class Test:
130 def method_and_var(self):
131 return "method"
132 def test(self):
133 return method_and_var
134 def actual_global(self):
135 return str("global")
136 def str(self):
137 return str(self)
138 return Test()
139
140t = test()
141verify(t.test() == "var")
142verify(t.method_and_var() == "method")
143verify(t.actual_global() == "global")
144
145method_and_var = "var"
146class Test:
147 # this class is not nested, so the rules are different
148 def method_and_var(self):
149 return "method"
150 def test(self):
151 return method_and_var
152 def actual_global(self):
153 return str("global")
154 def str(self):
155 return str(self)
156
Jeremy Hyltonde602482001-02-05 17:35:20 +0000157t = Test()
Jeremy Hylton4588c782001-01-25 20:11:23 +0000158verify(t.test() == "var")
159verify(t.method_and_var() == "method")
160verify(t.actual_global() == "global")
161
162print "10. recursion"
163
164def f(x):
165 def fact(n):
166 if n == 0:
167 return 1
168 else:
169 return n * fact(n - 1)
170 if x >= 0:
171 return fact(x)
172 else:
173 raise ValueError, "x must be >= 0"
174
175verify(f(6) == 720)
176
177
178print "11. unoptimized namespaces"
179
180def check_syntax(s):
181 try:
182 compile(s, '?', 'exec')
183 except SyntaxError:
184 pass
185 else:
186 raise TestFailed
187
Jeremy Hylton97a01672001-02-09 22:56:46 +0000188check_syntax("""def unoptimized_clash1(strip):
Jeremy Hylton4588c782001-01-25 20:11:23 +0000189 def f(s):
190 from string import *
191 return strip(s) # ambiguity: free or local
192 return f
Jeremy Hylton97a01672001-02-09 22:56:46 +0000193""")
Jeremy Hylton4588c782001-01-25 20:11:23 +0000194
Jeremy Hylton97a01672001-02-09 22:56:46 +0000195check_syntax("""def unoptimized_clash2():
Jeremy Hylton4588c782001-01-25 20:11:23 +0000196 from string import *
197 def f(s):
198 return strip(s) # ambiguity: global or local
199 return f
Jeremy Hylton97a01672001-02-09 22:56:46 +0000200""")
Jeremy Hylton4588c782001-01-25 20:11:23 +0000201
Jeremy Hylton97a01672001-02-09 22:56:46 +0000202check_syntax("""def unoptimized_clash2():
203 from string import *
204 def g():
205 def f(s):
206 return strip(s) # ambiguity: global or local
207 return f
208""")
209
210# XXX could allow this for exec with const argument, but what's the point
211check_syntax("""def error(y):
Jeremy Hylton4588c782001-01-25 20:11:23 +0000212 exec "a = 1"
213 def f(x):
214 return x + y
215 return f
Jeremy Hylton97a01672001-02-09 22:56:46 +0000216""")
Jeremy Hylton4588c782001-01-25 20:11:23 +0000217
Jeremy Hylton97a01672001-02-09 22:56:46 +0000218check_syntax("""def f(x):
Jeremy Hylton4588c782001-01-25 20:11:23 +0000219 def g():
220 return x
Jeremy Hylton97a01672001-02-09 22:56:46 +0000221 del x # can't del name
222""")
223
224check_syntax("""def f():
225 def g():
226 from string import *
227 return strip # global or local?
228""")
229
230# and verify a few cases that should work
231
232def noproblem1():
233 from string import *
234 f = lambda x:x
235
236def noproblem2():
237 from string import *
238 def f(x):
239 return x + 1
240
241def noproblem3():
242 from string import *
243 def f(x):
244 global y
245 y = x
Jeremy Hylton4588c782001-01-25 20:11:23 +0000246
247print "12. lambdas"
248
249f1 = lambda x: lambda y: x + y
250inc = f1(1)
251plus10 = f1(10)
252verify(inc(1) == 2)
253verify(plus10(5) == 15)
254
255f2 = lambda x: (lambda : lambda y: x + y)()
256inc = f2(1)
257plus10 = f2(10)
258verify(inc(1) == 2)
259verify(plus10(5) == 15)
260
261f3 = lambda x: lambda y: global_x + y
262global_x = 1
263inc = f3(None)
264verify(inc(2) == 3)
265
266f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y)
267g = f8(1, 2, 3)
268h = g(2, 4, 6)
269verify(h() == 18)
Jeremy Hyltonde602482001-02-05 17:35:20 +0000270
271print "13. UnboundLocal"
272
273def errorInOuter():
274 print y
275 def inner():
276 return y
277 y = 1
278
279def errorInInner():
280 def inner():
281 return y
282 inner()
283 y = 1
284
285try:
286 errorInOuter()
287except UnboundLocalError:
288 pass
289else:
290 raise TestFailed
291
292try:
293 errorInInner()
294except UnboundLocalError:
295 pass
296else:
297 raise TestFailed
Jeremy Hylton97a01672001-02-09 22:56:46 +0000298
299print "14. complex definitions"
300
301def makeReturner(*lst):
302 def returner():
303 return lst
304 return returner
305
306verify(makeReturner(1,2,3)() == (1,2,3))
307
308def makeReturner2(**kwargs):
309 def returner():
310 return kwargs
311 return returner
312
313verify(makeReturner2(a=11)()['a'] == 11)
314
315def makeAddPair((a, b)):
316 def addPair((c, d)):
317 return (a + c, b + d)
318 return addPair
319
320verify(makeAddPair((1, 2))((100, 200)) == (101,202))