1-- $Id: testes/goto.lua $
2-- See Copyright Notice in file all.lua
3
4collectgarbage()
5
6local function errmsg (code, m)
7 local st, msg = load(code)
8 assert(not st and string.find(msg, m))
9end
10
11-- cannot see label inside block
12errmsg([[ goto l1; do ::l1:: end ]], "label 'l1'")
13errmsg([[ do ::l1:: end goto l1; ]], "label 'l1'")
14
15-- repeated label
16errmsg([[ ::l1:: ::l1:: ]], "label 'l1'")
17errmsg([[ ::l1:: do ::l1:: end]], "label 'l1'")
18
19
20-- undefined label
21errmsg([[ goto l1; local aa ::l1:: ::l2:: print(3) ]], "local 'aa'")
22
23-- jumping over variable definition
24errmsg([[
25do local bb, cc; goto l1; end
26local aa
27::l1:: print(3)
28]], "local 'aa'")
29
30-- jumping into a block
31errmsg([[ do ::l1:: end goto l1 ]], "label 'l1'")
32errmsg([[ goto l1 do ::l1:: end ]], "label 'l1'")
33
34-- cannot continue a repeat-until with variables
35errmsg([[
36 repeat
37 if x then goto cont end
38 local xuxu = 10
39 ::cont::
40 until xuxu < x
41]], "local 'xuxu'")
42
43-- simple gotos
44local x
45do
46 local y = 12
47 goto l1
48 ::l2:: x = x + 1; goto l3
49 ::l1:: x = y; goto l2
50end
51::l3:: ::l3_1:: assert(x == 13)
52
53
54-- long labels
55do
56 local prog = [[
57 do
58 local a = 1
59 goto l%sa; a = a + 1
60 ::l%sa:: a = a + 10
61 goto l%sb; a = a + 2
62 ::l%sb:: a = a + 20
63 return a
64 end
65 ]]
66 local label = string.rep("0123456789", 40)
67 prog = string.format(prog, label, label, label, label)
68 assert(assert(load(prog))() == 31)
69end
70
71
72-- ok to jump over local dec. to end of block
73do
74 goto l1
75 local a = 23
76 x = a
77 ::l1::;
78end
79
80while true do
81 goto l4
82 goto l1 -- ok to jump over local dec. to end of block
83 goto l1 -- multiple uses of same label
84 local x = 45
85 ::l1:: ;;;
86end
87::l4:: assert(x == 13)
88
89if print then
90 goto l1 -- ok to jump over local dec. to end of block
91 error("should not be here")
92 goto l2 -- ok to jump over local dec. to end of block
93 local x
94 ::l1:: ; ::l2:: ;;
95else end
96
97-- to repeat a label in a different function is OK
98local function foo ()
99 local a = {}
100 goto l3
101 ::l1:: a[#a + 1] = 1; goto l2;
102 ::l2:: a[#a + 1] = 2; goto l5;
103 ::l3::
104 ::l3a:: a[#a + 1] = 3; goto l1;
105 ::l4:: a[#a + 1] = 4; goto l6;
106 ::l5:: a[#a + 1] = 5; goto l4;
107 ::l6:: assert(a[1] == 3 and a[2] == 1 and a[3] == 2 and
108 a[4] == 5 and a[5] == 4)
109 if not a[6] then a[6] = true; goto l3a end -- do it twice
110end
111
112::l6:: foo()
113
114
115do -- bug in 5.2 -> 5.3.2
116 local x
117 ::L1::
118 local y -- cannot join this SETNIL with previous one
119 assert(y == nil)
120 y = true
121 if x == nil then
122 x = 1
123 goto L1
124 else
125 x = x + 1
126 end
127 assert(x == 2 and y == true)
128end
129
130-- bug in 5.3
131do
132 local first = true
133 local a = false
134 if true then
135 goto LBL
136 ::loop::
137 a = true
138 ::LBL::
139 if first then
140 first = false
141 goto loop
142 end
143 end
144 assert(a)
145end
146
147do -- compiling infinite loops
148 goto escape -- do not run the infinite loops
149 ::a:: goto a
150 ::b:: goto c
151 ::c:: goto b
152end
153::escape::
154--------------------------------------------------------------------------------
155-- testing closing of upvalues
156
157local debug = require 'debug'
158
159local function foo ()
160 local t = {}
161 do
162 local i = 1
163 local a, b, c, d
164 t[1] = function () return a, b, c, d end
165 ::l1::
166 local b
167 do
168 local c
169 t[#t + 1] = function () return a, b, c, d end -- t[2], t[4], t[6]
170 if i > 2 then goto l2 end
171 do
172 local d
173 t[#t + 1] = function () return a, b, c, d end -- t[3], t[5]
174 i = i + 1
175 local a
176 goto l1
177 end
178 end
179 end
180 ::l2:: return t
181end
182
183local a = foo()
184assert(#a == 6)
185
186-- all functions share same 'a'
187for i = 2, 6 do
188 assert(debug.upvalueid(a[1], 1) == debug.upvalueid(a[i], 1))
189end
190
191-- 'b' and 'c' are shared among some of them
192for i = 2, 6 do
193 -- only a[1] uses external 'b'/'b'
194 assert(debug.upvalueid(a[1], 2) ~= debug.upvalueid(a[i], 2))
195 assert(debug.upvalueid(a[1], 3) ~= debug.upvalueid(a[i], 3))
196end
197
198for i = 3, 5, 2 do
199 -- inner functions share 'b'/'c' with previous ones
200 assert(debug.upvalueid(a[i], 2) == debug.upvalueid(a[i - 1], 2))
201 assert(debug.upvalueid(a[i], 3) == debug.upvalueid(a[i - 1], 3))
202 -- but not with next ones
203 assert(debug.upvalueid(a[i], 2) ~= debug.upvalueid(a[i + 1], 2))
204 assert(debug.upvalueid(a[i], 3) ~= debug.upvalueid(a[i + 1], 3))
205end
206
207-- only external 'd' is shared
208for i = 2, 6, 2 do
209 assert(debug.upvalueid(a[1], 4) == debug.upvalueid(a[i], 4))
210end
211
212-- internal 'd's are all different
213for i = 3, 5, 2 do
214 for j = 1, 6 do
215 assert((debug.upvalueid(a[i], 4) == debug.upvalueid(a[j], 4))
216 == (i == j))
217 end
218end
219
220--------------------------------------------------------------------------------
221-- testing if x goto optimizations
222
223local function testG (a)
224 if a == 1 then
225 goto l1
226 error("should never be here!")
227 elseif a == 2 then goto l2
228 elseif a == 3 then goto l3
229 elseif a == 4 then
230 goto l1 -- go to inside the block
231 error("should never be here!")
232 ::l1:: a = a + 1 -- must go to 'if' end
233 else
234 goto l4
235 ::l4a:: a = a * 2; goto l4b
236 error("should never be here!")
237 ::l4:: goto l4a
238 error("should never be here!")
239 ::l4b::
240 end
241 do return a end
242 ::l2:: do return "2" end
243 ::l3:: do return "3" end
244 ::l1:: return "1"
245end
246
247assert(testG(1) == "1")
248assert(testG(2) == "2")
249assert(testG(3) == "3")
250assert(testG(4) == 5)
251assert(testG(5) == 10)
252
253do
254 -- if x back goto out of scope of upvalue
255 local X
256 goto L1
257
258 ::L2:: goto L3
259
260 ::L1:: do
261 local a <close> = setmetatable({}, {__close = function () X = true end})
262 assert(X == nil)
263 if a then goto L2 end -- jumping back out of scope of 'a'
264 end
265
266 ::L3:: assert(X == true) -- checks that 'a' was correctly closed
267end
268--------------------------------------------------------------------------------
269
270
271print'OK'