summaryrefslogtreecommitdiff
path: root/testes/closure.lua
diff options
context:
space:
mode:
Diffstat (limited to 'testes/closure.lua')
-rw-r--r--testes/closure.lua247
1 files changed, 247 insertions, 0 deletions
diff --git a/testes/closure.lua b/testes/closure.lua
new file mode 100644
index 00000000..15897ae6
--- /dev/null
+++ b/testes/closure.lua
@@ -0,0 +1,247 @@
1-- $Id: closure.lua,v 1.59 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print "testing closures"
5
6local A,B = 0,{g=10}
7function f(x)
8 local a = {}
9 for i=1,1000 do
10 local y = 0
11 do
12 a[i] = function () B.g = B.g+1; y = y+x; return y+A end
13 end
14 end
15 local dummy = function () return a[A] end
16 collectgarbage()
17 A = 1; assert(dummy() == a[1]); A = 0;
18 assert(a[1]() == x)
19 assert(a[3]() == x)
20 collectgarbage()
21 assert(B.g == 12)
22 return a
23end
24
25local a = f(10)
26-- force a GC in this level
27local x = {[1] = {}} -- to detect a GC
28setmetatable(x, {__mode = 'kv'})
29while x[1] do -- repeat until GC
30 local a = A..A..A..A -- create garbage
31 A = A+1
32end
33assert(a[1]() == 20+A)
34assert(a[1]() == 30+A)
35assert(a[2]() == 10+A)
36collectgarbage()
37assert(a[2]() == 20+A)
38assert(a[2]() == 30+A)
39assert(a[3]() == 20+A)
40assert(a[8]() == 10+A)
41assert(getmetatable(x).__mode == 'kv')
42assert(B.g == 19)
43
44
45-- testing equality
46a = {}
47for i = 1, 5 do a[i] = function (x) return x + a + _ENV end end
48assert(a[3] == a[4] and a[4] == a[5])
49
50for i = 1, 5 do a[i] = function (x) return i + a + _ENV end end
51assert(a[3] ~= a[4] and a[4] ~= a[5])
52
53local function f()
54 return function (x) return math.sin(_ENV[x]) end
55end
56assert(f() == f())
57
58
59-- testing closures with 'for' control variable
60a = {}
61for i=1,10 do
62 a[i] = {set = function(x) i=x end, get = function () return i end}
63 if i == 3 then break end
64end
65assert(a[4] == nil)
66a[1].set(10)
67assert(a[2].get() == 2)
68a[2].set('a')
69assert(a[3].get() == 3)
70assert(a[2].get() == 'a')
71
72a = {}
73local t = {"a", "b"}
74for i = 1, #t do
75 local k = t[i]
76 a[i] = {set = function(x, y) i=x; k=y end,
77 get = function () return i, k end}
78 if i == 2 then break end
79end
80a[1].set(10, 20)
81local r,s = a[2].get()
82assert(r == 2 and s == 'b')
83r,s = a[1].get()
84assert(r == 10 and s == 20)
85a[2].set('a', 'b')
86r,s = a[2].get()
87assert(r == "a" and s == "b")
88
89
90-- testing closures with 'for' control variable x break
91for i=1,3 do
92 f = function () return i end
93 break
94end
95assert(f() == 1)
96
97for k = 1, #t do
98 local v = t[k]
99 f = function () return k, v end
100 break
101end
102assert(({f()})[1] == 1)
103assert(({f()})[2] == "a")
104
105
106-- testing closure x break x return x errors
107
108local b
109function f(x)
110 local first = 1
111 while 1 do
112 if x == 3 and not first then return end
113 local a = 'xuxu'
114 b = function (op, y)
115 if op == 'set' then
116 a = x+y
117 else
118 return a
119 end
120 end
121 if x == 1 then do break end
122 elseif x == 2 then return
123 else if x ~= 3 then error() end
124 end
125 first = nil
126 end
127end
128
129for i=1,3 do
130 f(i)
131 assert(b('get') == 'xuxu')
132 b('set', 10); assert(b('get') == 10+i)
133 b = nil
134end
135
136pcall(f, 4);
137assert(b('get') == 'xuxu')
138b('set', 10); assert(b('get') == 14)
139
140
141local w
142-- testing multi-level closure
143function f(x)
144 return function (y)
145 return function (z) return w+x+y+z end
146 end
147end
148
149y = f(10)
150w = 1.345
151assert(y(20)(30) == 60+w)
152
153-- testing closures x repeat-until
154
155local a = {}
156local i = 1
157repeat
158 local x = i
159 a[i] = function () i = x+1; return x end
160until i > 10 or a[i]() ~= x
161assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4)
162
163
164-- testing closures created in 'then' and 'else' parts of 'if's
165a = {}
166for i = 1, 10 do
167 if i % 3 == 0 then
168 local y = 0
169 a[i] = function (x) local t = y; y = x; return t end
170 elseif i % 3 == 1 then
171 goto L1
172 error'not here'
173 ::L1::
174 local y = 1
175 a[i] = function (x) local t = y; y = x; return t end
176 elseif i % 3 == 2 then
177 local t
178 goto l4
179 ::l4a:: a[i] = t; goto l4b
180 error("should never be here!")
181 ::l4::
182 local y = 2
183 t = function (x) local t = y; y = x; return t end
184 goto l4a
185 error("should never be here!")
186 ::l4b::
187 end
188end
189
190for i = 1, 10 do
191 assert(a[i](i * 10) == i % 3 and a[i]() == i * 10)
192end
193
194print'+'
195
196
197-- test for correctly closing upvalues in tail calls of vararg functions
198local function t ()
199 local function c(a,b) assert(a=="test" and b=="OK") end
200 local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end
201 local x = 1
202 return v(function() return x end)
203end
204t()
205
206
207-- test for debug manipulation of upvalues
208local debug = require'debug'
209
210do
211 local a , b, c = 3, 5, 7
212 foo1 = function () return a+b end;
213 foo2 = function () return b+a end;
214 do
215 local a = 10
216 foo3 = function () return a+b end;
217 end
218end
219
220assert(debug.upvalueid(foo1, 1))
221assert(debug.upvalueid(foo1, 2))
222assert(not pcall(debug.upvalueid, foo1, 3))
223assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2))
224assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1))
225assert(debug.upvalueid(foo3, 1))
226assert(debug.upvalueid(foo1, 1) ~= debug.upvalueid(foo3, 1))
227assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo3, 2))
228
229assert(debug.upvalueid(string.gmatch("x", "x"), 1) ~= nil)
230
231assert(foo1() == 3 + 5 and foo2() == 5 + 3)
232debug.upvaluejoin(foo1, 2, foo2, 2)
233assert(foo1() == 3 + 3 and foo2() == 5 + 3)
234assert(foo3() == 10 + 5)
235debug.upvaluejoin(foo3, 2, foo2, 1)
236assert(foo3() == 10 + 5)
237debug.upvaluejoin(foo3, 2, foo2, 2)
238assert(foo3() == 10 + 3)
239
240assert(not pcall(debug.upvaluejoin, foo1, 3, foo2, 1))
241assert(not pcall(debug.upvaluejoin, foo1, 1, foo2, 3))
242assert(not pcall(debug.upvaluejoin, foo1, 0, foo2, 1))
243assert(not pcall(debug.upvaluejoin, print, 1, foo2, 1))
244assert(not pcall(debug.upvaluejoin, {}, 1, foo2, 1))
245assert(not pcall(debug.upvaluejoin, foo1, 1, print, 1))
246
247print'OK'