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