diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-12-17 14:46:37 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-12-17 14:46:37 -0200 |
commit | 063d4e4543088e7a21965bda8ee5a0f952a9029e (patch) | |
tree | 6c3f2f8e98c26f071a94a32f9f2754396a66a9de /testes/closure.lua | |
parent | e354c6355e7f48e087678ec49e340ca0696725b1 (diff) | |
download | lua-5.3.5.tar.gz lua-5.3.5.tar.bz2 lua-5.3.5.zip |
Lua 5.3.5 ported to gitv5.3.5
This is the first commit for the branch Lua 5.3. All source files
were copied from the official distribution of 5.3.5 in the Lua site.
The test files are the same of 5.3.4. The manual came from the
previous RCS repository, revision 1.167.1.2.
Diffstat (limited to '')
-rw-r--r-- | testes/closure.lua | 247 |
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 | |||
4 | print "testing closures" | ||
5 | |||
6 | local A,B = 0,{g=10} | ||
7 | function 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 | ||
23 | end | ||
24 | |||
25 | local a = f(10) | ||
26 | -- force a GC in this level | ||
27 | local x = {[1] = {}} -- to detect a GC | ||
28 | setmetatable(x, {__mode = 'kv'}) | ||
29 | while x[1] do -- repeat until GC | ||
30 | local a = A..A..A..A -- create garbage | ||
31 | A = A+1 | ||
32 | end | ||
33 | assert(a[1]() == 20+A) | ||
34 | assert(a[1]() == 30+A) | ||
35 | assert(a[2]() == 10+A) | ||
36 | collectgarbage() | ||
37 | assert(a[2]() == 20+A) | ||
38 | assert(a[2]() == 30+A) | ||
39 | assert(a[3]() == 20+A) | ||
40 | assert(a[8]() == 10+A) | ||
41 | assert(getmetatable(x).__mode == 'kv') | ||
42 | assert(B.g == 19) | ||
43 | |||
44 | |||
45 | -- testing equality | ||
46 | a = {} | ||
47 | for i = 1, 5 do a[i] = function (x) return x + a + _ENV end end | ||
48 | assert(a[3] == a[4] and a[4] == a[5]) | ||
49 | |||
50 | for i = 1, 5 do a[i] = function (x) return i + a + _ENV end end | ||
51 | assert(a[3] ~= a[4] and a[4] ~= a[5]) | ||
52 | |||
53 | local function f() | ||
54 | return function (x) return math.sin(_ENV[x]) end | ||
55 | end | ||
56 | assert(f() == f()) | ||
57 | |||
58 | |||
59 | -- testing closures with 'for' control variable | ||
60 | a = {} | ||
61 | for 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 | ||
64 | end | ||
65 | assert(a[4] == nil) | ||
66 | a[1].set(10) | ||
67 | assert(a[2].get() == 2) | ||
68 | a[2].set('a') | ||
69 | assert(a[3].get() == 3) | ||
70 | assert(a[2].get() == 'a') | ||
71 | |||
72 | a = {} | ||
73 | local t = {"a", "b"} | ||
74 | for 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 | ||
79 | end | ||
80 | a[1].set(10, 20) | ||
81 | local r,s = a[2].get() | ||
82 | assert(r == 2 and s == 'b') | ||
83 | r,s = a[1].get() | ||
84 | assert(r == 10 and s == 20) | ||
85 | a[2].set('a', 'b') | ||
86 | r,s = a[2].get() | ||
87 | assert(r == "a" and s == "b") | ||
88 | |||
89 | |||
90 | -- testing closures with 'for' control variable x break | ||
91 | for i=1,3 do | ||
92 | f = function () return i end | ||
93 | break | ||
94 | end | ||
95 | assert(f() == 1) | ||
96 | |||
97 | for k = 1, #t do | ||
98 | local v = t[k] | ||
99 | f = function () return k, v end | ||
100 | break | ||
101 | end | ||
102 | assert(({f()})[1] == 1) | ||
103 | assert(({f()})[2] == "a") | ||
104 | |||
105 | |||
106 | -- testing closure x break x return x errors | ||
107 | |||
108 | local b | ||
109 | function 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 | ||
127 | end | ||
128 | |||
129 | for i=1,3 do | ||
130 | f(i) | ||
131 | assert(b('get') == 'xuxu') | ||
132 | b('set', 10); assert(b('get') == 10+i) | ||
133 | b = nil | ||
134 | end | ||
135 | |||
136 | pcall(f, 4); | ||
137 | assert(b('get') == 'xuxu') | ||
138 | b('set', 10); assert(b('get') == 14) | ||
139 | |||
140 | |||
141 | local w | ||
142 | -- testing multi-level closure | ||
143 | function f(x) | ||
144 | return function (y) | ||
145 | return function (z) return w+x+y+z end | ||
146 | end | ||
147 | end | ||
148 | |||
149 | y = f(10) | ||
150 | w = 1.345 | ||
151 | assert(y(20)(30) == 60+w) | ||
152 | |||
153 | -- testing closures x repeat-until | ||
154 | |||
155 | local a = {} | ||
156 | local i = 1 | ||
157 | repeat | ||
158 | local x = i | ||
159 | a[i] = function () i = x+1; return x end | ||
160 | until i > 10 or a[i]() ~= x | ||
161 | assert(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 | ||
165 | a = {} | ||
166 | for 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 | ||
188 | end | ||
189 | |||
190 | for i = 1, 10 do | ||
191 | assert(a[i](i * 10) == i % 3 and a[i]() == i * 10) | ||
192 | end | ||
193 | |||
194 | print'+' | ||
195 | |||
196 | |||
197 | -- test for correctly closing upvalues in tail calls of vararg functions | ||
198 | local 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) | ||
203 | end | ||
204 | t() | ||
205 | |||
206 | |||
207 | -- test for debug manipulation of upvalues | ||
208 | local debug = require'debug' | ||
209 | |||
210 | do | ||
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 | ||
218 | end | ||
219 | |||
220 | assert(debug.upvalueid(foo1, 1)) | ||
221 | assert(debug.upvalueid(foo1, 2)) | ||
222 | assert(not pcall(debug.upvalueid, foo1, 3)) | ||
223 | assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2)) | ||
224 | assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1)) | ||
225 | assert(debug.upvalueid(foo3, 1)) | ||
226 | assert(debug.upvalueid(foo1, 1) ~= debug.upvalueid(foo3, 1)) | ||
227 | assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo3, 2)) | ||
228 | |||
229 | assert(debug.upvalueid(string.gmatch("x", "x"), 1) ~= nil) | ||
230 | |||
231 | assert(foo1() == 3 + 5 and foo2() == 5 + 3) | ||
232 | debug.upvaluejoin(foo1, 2, foo2, 2) | ||
233 | assert(foo1() == 3 + 3 and foo2() == 5 + 3) | ||
234 | assert(foo3() == 10 + 5) | ||
235 | debug.upvaluejoin(foo3, 2, foo2, 1) | ||
236 | assert(foo3() == 10 + 5) | ||
237 | debug.upvaluejoin(foo3, 2, foo2, 2) | ||
238 | assert(foo3() == 10 + 3) | ||
239 | |||
240 | assert(not pcall(debug.upvaluejoin, foo1, 3, foo2, 1)) | ||
241 | assert(not pcall(debug.upvaluejoin, foo1, 1, foo2, 3)) | ||
242 | assert(not pcall(debug.upvaluejoin, foo1, 0, foo2, 1)) | ||
243 | assert(not pcall(debug.upvaluejoin, print, 1, foo2, 1)) | ||
244 | assert(not pcall(debug.upvaluejoin, {}, 1, foo2, 1)) | ||
245 | assert(not pcall(debug.upvaluejoin, foo1, 1, print, 1)) | ||
246 | |||
247 | print'OK' | ||