aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--makefile2
-rw-r--r--spec/inputs/goto.yue4
-rw-r--r--spec/inputs/loops.yue8
-rw-r--r--spec/inputs/test/loops_spec.yue6
-rw-r--r--spec/outputs/5.1/loops.lua381
-rw-r--r--spec/outputs/5.1/test/loops_spec.lua69
-rw-r--r--spec/outputs/goto.lua4
-rw-r--r--spec/outputs/loops.lua204
-rw-r--r--spec/outputs/test/loops_spec.lua51
-rw-r--r--src/3rdParty/lua/lauxlib.c8
-rw-r--r--src/3rdParty/lua/lobject.c2
-rw-r--r--src/3rdParty/lua/loslib.c4
-rw-r--r--src/3rdParty/lua/ltablib.c2
-rw-r--r--src/3rdParty/lua/luaconf.h5
-rw-r--r--src/3rdParty/lua/lutf8lib.c27
-rw-r--r--src/3rdParty/lua/lvm.c4
-rw-r--r--src/3rdParty/lua/lvm.h5
-rwxr-xr-xsrc/yuescript/yue_ast.h1
-rw-r--r--[-rwxr-xr-x]src/yuescript/yue_compiler.cpp348
19 files changed, 811 insertions, 324 deletions
diff --git a/makefile b/makefile
index 11e59f3..0c86ccb 100644
--- a/makefile
+++ b/makefile
@@ -282,6 +282,8 @@ gen: release
282 @$(START_TIME) 282 @$(START_TIME)
283 @./$(BIN_NAME) $(TEST_INPUT) -t $(GEN_OUTPUT) --tl_enabled 283 @./$(BIN_NAME) $(TEST_INPUT) -t $(GEN_OUTPUT) --tl_enabled
284 @./$(BIN_NAME) $(TEST_INPUT)/teal-lang.yue -o $(GEN_OUTPUT)/teal-lang.lua 284 @./$(BIN_NAME) $(TEST_INPUT)/teal-lang.yue -o $(GEN_OUTPUT)/teal-lang.lua
285 @./$(BIN_NAME) $(TEST_INPUT)/loops.yue -o $(GEN_OUTPUT)/5.1/loops.lua --target=5.1
286 @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(GEN_OUTPUT)/5.1/test/loops_spec.lua --target=5.1
285 @echo -en "Compile time: " 287 @echo -en "Compile time: "
286 @$(END_TIME) 288 @$(END_TIME)
287 289
diff --git a/spec/inputs/goto.yue b/spec/inputs/goto.yue
index 1197251..61584ca 100644
--- a/spec/inputs/goto.yue
+++ b/spec/inputs/goto.yue
@@ -10,8 +10,8 @@ do
10 for z = 1, 10 do for y = 1, 10 do for x = 1, 10 10 for z = 1, 10 do for y = 1, 10 do for x = 1, 10
11 if x^2 + y^2 == z^2 11 if x^2 + y^2 == z^2
12 print 'found a Pythagorean triple:', x, y, z 12 print 'found a Pythagorean triple:', x, y, z
13 goto done 13 goto ok
14 ::done:: 14 ::ok::
15 15
16do 16do
17 for z = 1, 10 17 for z = 1, 10
diff --git a/spec/inputs/loops.yue b/spec/inputs/loops.yue
index d03e661..d997c65 100644
--- a/spec/inputs/loops.yue
+++ b/spec/inputs/loops.yue
@@ -111,10 +111,10 @@ until a == 10
111 111
112x = 0 112x = 0
113repeat 113repeat
114 x += 1 114 x += 1
115 y = x 115 y = x
116 continue if x < 5 116 continue if x < 5
117 print y 117 print y
118until y == 10 118until y == 10
119 119
120a = 3 120a = 3
diff --git a/spec/inputs/test/loops_spec.yue b/spec/inputs/test/loops_spec.yue
index 817919f..a115581 100644
--- a/spec/inputs/test/loops_spec.yue
+++ b/spec/inputs/test/loops_spec.yue
@@ -5,8 +5,8 @@ describe "loops", ->
5 continue if x % 2 == 1 5 continue if x % 2 == 1
6 x 6 x
7 7
8 assert.same output, { 2,4,6 } 8 assert.same { 2,4,6 }, output
9 9
10 it "continue in repeat", -> 10 it "continue in repeat", ->
11 output = {} 11 output = {}
12 a = 0 12 a = 0
@@ -19,5 +19,5 @@ describe "loops", ->
19 output[] = a 19 output[] = a
20 until a == 8 20 until a == 8
21 21
22 assert.same output, { 1,2,4 } 22 assert.same { 1,2,4 }, output
23 23
diff --git a/spec/outputs/5.1/loops.lua b/spec/outputs/5.1/loops.lua
new file mode 100644
index 0000000..a3b9548
--- /dev/null
+++ b/spec/outputs/5.1/loops.lua
@@ -0,0 +1,381 @@
1for x = 1, 10 do
2 print("yeah")
3end
4for x = 1, #something do
5 print("yeah")
6end
7for y = 100, 60, -3 do
8 print("count down", y)
9end
10for a = 1, 10 do
11 print("okay")
12end
13for a = 1, 10 do
14 for b = 2, 43 do
15 print(a, b)
16 end
17end
18for i in iter do
19 for j in yeah do
20 local x = 343 + i + j
21 print(i, j)
22 end
23end
24local _list_0 = something
25for _index_0 = 1, #_list_0 do
26 local x = _list_0[_index_0]
27 print(x)
28end
29for k, v in pairs(hello) do
30 print(k, v)
31end
32for x in y, z do
33 print(x)
34end
35for x in y, z, k do
36 print(x)
37end
38local _list_1 = modules
39for _index_0 = 1, #_list_1 do
40 local name, members = _list_1[_index_0]
41 print(name, member)
42end
43local x
44x = function()
45 for x in y do
46 local _ = y
47 end
48end
49local hello = {
50 1,
51 2,
52 3,
53 4,
54 5
55}
56do
57 local _accum_0 = { }
58 local _len_0 = 1
59 for _index_0 = 1, #hello do
60 local y = hello[_index_0]
61 if y % 2 == 0 then
62 _accum_0[_len_0] = y
63 end
64 _len_0 = _len_0 + 1
65 end
66 x = _accum_0
67end
68x = function()
69 for _index_0 = 1, #hello do
70 local x = hello[_index_0]
71 local _ = y
72 end
73end
74local t
75do
76 local _accum_0 = { }
77 local _len_0 = 1
78 for i = 10, 20 do
79 _accum_0[_len_0] = i * 2
80 _len_0 = _len_0 + 1
81 end
82 t = _accum_0
83end
84local hmm = 0
85local y
86do
87 local _accum_0 = { }
88 local _len_0 = 1
89 for j = 3, 30, 8 do
90 hmm = hmm + 1
91 _accum_0[_len_0] = j * hmm
92 _len_0 = _len_0 + 1
93 end
94 y = _accum_0
95end
96local _
97_ = function()
98 for k = 10, 40 do
99 _ = "okay"
100 end
101end
102_ = function()
103 local _accum_0 = { }
104 local _len_0 = 1
105 for k = 10, 40 do
106 _accum_0[_len_0] = "okay"
107 _len_0 = _len_0 + 1
108 end
109 return _accum_0
110end
111while true do
112 print("name")
113end
114while 5 + 5 do
115 print("okay world")
116 working(man)
117end
118while also do
119 i(work(too))
120 _ = "okay"
121end
122local i = 0
123do
124 local _accum_0 = { }
125 local _len_0 = 1
126 while i < 10 do
127 i = i + 1
128 _len_0 = _len_0 + 1
129 end
130 x = _accum_0
131end
132do
133 local _accum_0 = { }
134 local _len_0 = 1
135 local _list_2 = 3
136 for _index_0 = 1, #_list_2 do
137 local thing = _list_2[_index_0]
138 y = "hello"
139 _len_0 = _len_0 + 1
140 end
141 x = _accum_0
142end
143do
144 local _accum_0 = { }
145 local _len_0 = 1
146 for x = 1, 2 do
147 y = "hello"
148 _len_0 = _len_0 + 1
149 end
150 x = _accum_0
151end
152while true do
153 local _continue_0 = false
154 repeat
155 if false then
156 _continue_0 = true
157 break
158 end
159 print("yes")
160 if true then
161 break
162 end
163 print("no")
164 _continue_0 = true
165 until true
166 if not _continue_0 then
167 break
168 end
169end
170for i = 1, 10 do
171 while true do
172 local _continue_0 = false
173 repeat
174 do
175 if not true then
176 _continue_0 = true
177 break
178 end
179 break
180 end
181 _continue_0 = true
182 until true
183 if not _continue_0 then
184 break
185 end
186 end
187end
188local a = 1
189repeat
190 local _cond_0 = false
191 local _continue_0 = false
192 repeat
193 a = a + 1
194 if a == 5 then
195 _cond_0 = a == 10
196 _continue_0 = true
197 break
198 end
199 if a == 6 then
200 break
201 end
202 print(a)
203 _cond_0 = a == 10
204 _continue_0 = true
205 until true
206 if not _continue_0 then
207 break
208 end
209until _cond_0
210x = 0
211repeat
212 local _cond_0 = false
213 local _continue_0 = false
214 repeat
215 x = x + 1
216 y = x
217 if x < 5 then
218 _cond_0 = y == 10
219 _continue_0 = true
220 break
221 end
222 print(y)
223 _cond_0 = y == 10
224 _continue_0 = true
225 until true
226 if not _continue_0 then
227 break
228 end
229until _cond_0
230a = 3
231while not (a == 0) do
232 a = a - 1
233end
234local done = false
235while not done do
236 done = true
237end
238repeat
239 print("hello")
240until true
241while not done do
242 x = 10
243 repeat
244 x = x - 1
245 until x == 0
246end
247while not cond do
248 print("okay")
249end
250for x = 1, 10 do
251 local _continue_0 = false
252 repeat
253 if x > 3 and x < 7 then
254 _continue_0 = true
255 break
256 end
257 print(x)
258 _continue_0 = true
259 until true
260 if not _continue_0 then
261 break
262 end
263end
264local list
265do
266 local _accum_0 = { }
267 local _len_0 = 1
268 for x = 1, 10 do
269 local _continue_0 = false
270 repeat
271 if x > 3 and x < 7 then
272 _continue_0 = true
273 break
274 end
275 _accum_0[_len_0] = x
276 _len_0 = _len_0 + 1
277 _continue_0 = true
278 until true
279 if not _continue_0 then
280 break
281 end
282 end
283 list = _accum_0
284end
285local _list_2 = {
286 1,
287 2,
288 3,
289 4,
290 5,
291 6
292}
293for _index_0 = 1, #_list_2 do
294 local a = _list_2[_index_0]
295 local _continue_0 = false
296 repeat
297 if a == 1 then
298 _continue_0 = true
299 break
300 end
301 if a == 3 then
302 _continue_0 = true
303 break
304 end
305 print(a)
306 _continue_0 = true
307 until true
308 if not _continue_0 then
309 break
310 end
311end
312for x = 1, 10 do
313 local _continue_0 = false
314 repeat
315 if x % 2 == 0 then
316 _continue_0 = true
317 break
318 end
319 for y = 2, 12 do
320 local _continue_1 = false
321 repeat
322 if y % 3 == 0 then
323 _continue_1 = true
324 break
325 end
326 _continue_1 = true
327 until true
328 if not _continue_1 then
329 break
330 end
331 end
332 _continue_0 = true
333 until true
334 if not _continue_0 then
335 break
336 end
337end
338while true do
339 local _continue_0 = false
340 repeat
341 do
342 if false then
343 _continue_0 = true
344 break
345 end
346 break
347 end
348 _continue_0 = true
349 until true
350 if not _continue_0 then
351 break
352 end
353end
354while true do
355 local _continue_0 = false
356 repeat
357 if false then
358 _continue_0 = true
359 break
360 end
361 do
362 return 22
363 end
364 _continue_0 = true
365 until true
366 if not _continue_0 then
367 break
368 end
369end
370do
371 local xxx = {
372 1,
373 2,
374 3,
375 4
376 }
377 for _index_0 = 1, #xxx do
378 local thing = xxx[_index_0]
379 print(thing)
380 end
381end
diff --git a/spec/outputs/5.1/test/loops_spec.lua b/spec/outputs/5.1/test/loops_spec.lua
new file mode 100644
index 0000000..bad17a6
--- /dev/null
+++ b/spec/outputs/5.1/test/loops_spec.lua
@@ -0,0 +1,69 @@
1return describe("loops", function()
2 it("should continue", function()
3 local input = {
4 1,
5 2,
6 3,
7 4,
8 5,
9 6
10 }
11 local output
12 do
13 local _accum_0 = { }
14 local _len_0 = 1
15 for _index_0 = 1, #input do
16 local x = input[_index_0]
17 local _continue_0 = false
18 repeat
19 if x % 2 == 1 then
20 _continue_0 = true
21 break
22 end
23 _accum_0[_len_0] = x
24 _len_0 = _len_0 + 1
25 _continue_0 = true
26 until true
27 if not _continue_0 then
28 break
29 end
30 end
31 output = _accum_0
32 end
33 return assert.same({
34 2,
35 4,
36 6
37 }, output)
38 end)
39 return it("continue in repeat", function()
40 local output = { }
41 local a = 0
42 repeat
43 local _cond_0 = false
44 local _continue_0 = false
45 repeat
46 a = a + 1
47 if a == 3 then
48 _cond_0 = a == 8
49 _continue_0 = true
50 break
51 end
52 if a == 5 then
53 break
54 end
55 output[#output + 1] = a
56 _cond_0 = a == 8
57 _continue_0 = true
58 until true
59 if not _continue_0 then
60 break
61 end
62 until _cond_0
63 return assert.same({
64 1,
65 2,
66 4
67 }, output)
68 end)
69end)
diff --git a/spec/outputs/goto.lua b/spec/outputs/goto.lua
index d1f7b77..421508a 100644
--- a/spec/outputs/goto.lua
+++ b/spec/outputs/goto.lua
@@ -14,12 +14,12 @@ do
14 for x = 1, 10 do 14 for x = 1, 10 do
15 if x ^ 2 + y ^ 2 == z ^ 2 then 15 if x ^ 2 + y ^ 2 == z ^ 2 then
16 print('found a Pythagorean triple:', x, y, z) 16 print('found a Pythagorean triple:', x, y, z)
17 goto done 17 goto ok
18 end 18 end
19 end 19 end
20 end 20 end
21 end 21 end
22 ::done:: 22 ::ok::
23end 23end
24do 24do
25 for z = 1, 10 do 25 for z = 1, 10 do
diff --git a/spec/outputs/loops.lua b/spec/outputs/loops.lua
index e5c189e..9c16ee4 100644
--- a/spec/outputs/loops.lua
+++ b/spec/outputs/loops.lua
@@ -150,83 +150,47 @@ do
150 x = _accum_0 150 x = _accum_0
151end 151end
152while true do 152while true do
153 local _continue_0 = false 153 if false then
154 repeat 154 goto _continue_0
155 if false then 155 end
156 _continue_0 = true 156 print("yes")
157 break 157 if true then
158 end
159 print("yes")
160 if true then
161 break
162 end
163 print("no")
164 _continue_0 = true
165 until true
166 if not _continue_0 then
167 break 158 break
168 end 159 end
160 print("no")
161 ::_continue_0::
169end 162end
170for i = 1, 10 do 163for i = 1, 10 do
171 while true do 164 while true do
172 local _continue_0 = false 165 if not true then
173 repeat 166 goto _continue_1
174 do
175 if not true then
176 _continue_0 = true
177 break
178 end
179 break
180 end
181 _continue_0 = true
182 until true
183 if not _continue_0 then
184 break
185 end 167 end
168 break
169 ::_continue_1::
186 end 170 end
187end 171end
188local a = 1 172local a = 1
189repeat 173repeat
190 local _cond_0 = false 174 a = a + 1
191 local _continue_0 = false 175 if a == 5 then
192 repeat 176 goto _continue_2
193 a = a + 1 177 end
194 if a == 5 then 178 if a == 6 then
195 _cond_0 = a == 10
196 _continue_0 = true
197 break
198 end
199 if a == 6 then
200 break
201 end
202 print(a)
203 _cond_0 = a == 10
204 _continue_0 = true
205 until true
206 if not _continue_0 then
207 break 179 break
208 end 180 end
209until _cond_0 181 print(a)
182 ::_continue_2::
183until a == 10
210x = 0 184x = 0
211repeat 185repeat
212 local _cond_0 = false 186 x = x + 1
213 local _continue_0 = false 187 y = x
214 repeat 188 if x < 5 then
215 x = x + 1 189 goto _continue_3
216 y = x
217 if x < 5 then
218 _cond_0 = y == 10
219 _continue_0 = true
220 break
221 end
222 print(y)
223 _cond_0 = y == 10
224 _continue_0 = true
225 until true
226 if not _continue_0 then
227 break
228 end 190 end
229until _cond_0 191 print(y)
192 ::_continue_3::
193until y == 10
230a = 3 194a = 3
231while not (a == 0) do 195while not (a == 0) do
232 a = a - 1 196 a = a - 1
@@ -248,37 +212,23 @@ while not cond do
248 print("okay") 212 print("okay")
249end 213end
250for x = 1, 10 do 214for x = 1, 10 do
251 local _continue_0 = false 215 if x > 3 and x < 7 then
252 repeat 216 goto _continue_4
253 if x > 3 and x < 7 then
254 _continue_0 = true
255 break
256 end
257 print(x)
258 _continue_0 = true
259 until true
260 if not _continue_0 then
261 break
262 end 217 end
218 print(x)
219 ::_continue_4::
263end 220end
264local list 221local list
265do 222do
266 local _accum_0 = { } 223 local _accum_0 = { }
267 local _len_0 = 1 224 local _len_0 = 1
268 for x = 1, 10 do 225 for x = 1, 10 do
269 local _continue_0 = false 226 if x > 3 and x < 7 then
270 repeat 227 goto _continue_5
271 if x > 3 and x < 7 then
272 _continue_0 = true
273 break
274 end
275 _accum_0[_len_0] = x
276 _len_0 = _len_0 + 1
277 _continue_0 = true
278 until true
279 if not _continue_0 then
280 break
281 end 228 end
229 _accum_0[_len_0] = x
230 _len_0 = _len_0 + 1
231 ::_continue_5::
282 end 232 end
283 list = _accum_0 233 list = _accum_0
284end 234end
@@ -292,78 +242,42 @@ local _list_2 = {
292} 242}
293for _index_0 = 1, #_list_2 do 243for _index_0 = 1, #_list_2 do
294 local a = _list_2[_index_0] 244 local a = _list_2[_index_0]
295 local _continue_0 = false 245 if a == 1 then
296 repeat 246 goto _continue_6
297 if a == 1 then
298 _continue_0 = true
299 break
300 end
301 if a == 3 then
302 _continue_0 = true
303 break
304 end
305 print(a)
306 _continue_0 = true
307 until true
308 if not _continue_0 then
309 break
310 end 247 end
248 if a == 3 then
249 goto _continue_6
250 end
251 print(a)
252 ::_continue_6::
311end 253end
312for x = 1, 10 do 254for x = 1, 10 do
313 local _continue_0 = false 255 if x % 2 == 0 then
314 repeat 256 goto _continue_7
315 if x % 2 == 0 then 257 end
316 _continue_0 = true 258 for y = 2, 12 do
317 break 259 if y % 3 == 0 then
318 end 260 goto _continue_8
319 for y = 2, 12 do
320 local _continue_1 = false
321 repeat
322 if y % 3 == 0 then
323 _continue_1 = true
324 break
325 end
326 _continue_1 = true
327 until true
328 if not _continue_1 then
329 break
330 end
331 end 261 end
332 _continue_0 = true 262 ::_continue_8::
333 until true
334 if not _continue_0 then
335 break
336 end 263 end
264 ::_continue_7::
337end 265end
338while true do 266while true do
339 local _continue_0 = false 267 if false then
340 repeat 268 goto _continue_9
341 do
342 if false then
343 _continue_0 = true
344 break
345 end
346 break
347 end
348 _continue_0 = true
349 until true
350 if not _continue_0 then
351 break
352 end 269 end
270 break
271 ::_continue_9::
353end 272end
354while true do 273while true do
355 local _continue_0 = false 274 if false then
356 repeat 275 goto _continue_10
357 if false then 276 end
358 _continue_0 = true 277 do
359 break
360 end
361 return 22 278 return 22
362 _continue_0 = true
363 until true
364 if not _continue_0 then
365 break
366 end 279 end
280 ::_continue_10::
367end 281end
368do 282do
369 local xxx = { 283 local xxx = {
diff --git a/spec/outputs/test/loops_spec.lua b/spec/outputs/test/loops_spec.lua
index 34f2e9c..9c85e1a 100644
--- a/spec/outputs/test/loops_spec.lua
+++ b/spec/outputs/test/loops_spec.lua
@@ -14,56 +14,39 @@ return describe("loops", function()
14 local _len_0 = 1 14 local _len_0 = 1
15 for _index_0 = 1, #input do 15 for _index_0 = 1, #input do
16 local x = input[_index_0] 16 local x = input[_index_0]
17 local _continue_0 = false 17 if x % 2 == 1 then
18 repeat 18 goto _continue_0
19 if x % 2 == 1 then
20 _continue_0 = true
21 break
22 end
23 _accum_0[_len_0] = x
24 _len_0 = _len_0 + 1
25 _continue_0 = true
26 until true
27 if not _continue_0 then
28 break
29 end 19 end
20 _accum_0[_len_0] = x
21 _len_0 = _len_0 + 1
22 ::_continue_0::
30 end 23 end
31 output = _accum_0 24 output = _accum_0
32 end 25 end
33 return assert.same(output, { 26 return assert.same({
34 2, 27 2,
35 4, 28 4,
36 6 29 6
37 }) 30 }, output)
38 end) 31 end)
39 return it("continue in repeat", function() 32 return it("continue in repeat", function()
40 local output = { } 33 local output = { }
41 local a = 0 34 local a = 0
42 repeat 35 repeat
43 local _cond_0 = false 36 a = a + 1
44 local _continue_0 = false 37 if a == 3 then
45 repeat 38 goto _continue_0
46 a = a + 1 39 end
47 if a == 3 then 40 if a == 5 then
48 _cond_0 = a == 8
49 _continue_0 = true
50 break
51 end
52 if a == 5 then
53 break
54 end
55 output[#output + 1] = a
56 _cond_0 = a == 8
57 _continue_0 = true
58 until true
59 if not _continue_0 then
60 break 41 break
61 end 42 end
62 until _cond_0 43 output[#output + 1] = a
63 return assert.same(output, { 44 ::_continue_0::
45 until a == 8
46 return assert.same({
64 1, 47 1,
65 2, 48 2,
66 4 49 4
67 }) 50 }, output)
68 end) 51 end)
69end) 52end)
diff --git a/src/3rdParty/lua/lauxlib.c b/src/3rdParty/lua/lauxlib.c
index cba5df9..4ca6c65 100644
--- a/src/3rdParty/lua/lauxlib.c
+++ b/src/3rdParty/lua/lauxlib.c
@@ -526,14 +526,14 @@ static void newbox (lua_State *L) {
526 526
527/* 527/*
528** Compute new size for buffer 'B', enough to accommodate extra 'sz' 528** Compute new size for buffer 'B', enough to accommodate extra 'sz'
529** bytes. (The test for "double is not big enough" also gets the 529** bytes. (The test for "not big enough" also gets the case when the
530** case when the multiplication by 2 overflows.) 530** computation of 'newsize' overflows.)
531*/ 531*/
532static size_t newbuffsize (luaL_Buffer *B, size_t sz) { 532static size_t newbuffsize (luaL_Buffer *B, size_t sz) {
533 size_t newsize = B->size * 2; /* double buffer size */ 533 size_t newsize = (B->size / 2) * 3; /* buffer size * 1.5 */
534 if (l_unlikely(MAX_SIZET - sz < B->n)) /* overflow in (B->n + sz)? */ 534 if (l_unlikely(MAX_SIZET - sz < B->n)) /* overflow in (B->n + sz)? */
535 return luaL_error(B->L, "buffer too large"); 535 return luaL_error(B->L, "buffer too large");
536 if (newsize < B->n + sz) /* double is not big enough? */ 536 if (newsize < B->n + sz) /* not big enough? */
537 newsize = B->n + sz; 537 newsize = B->n + sz;
538 return newsize; 538 return newsize;
539} 539}
diff --git a/src/3rdParty/lua/lobject.c b/src/3rdParty/lua/lobject.c
index a2c0060..03e2798 100644
--- a/src/3rdParty/lua/lobject.c
+++ b/src/3rdParty/lua/lobject.c
@@ -62,7 +62,7 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
62 case LUA_OPBOR: return intop(|, v1, v2); 62 case LUA_OPBOR: return intop(|, v1, v2);
63 case LUA_OPBXOR: return intop(^, v1, v2); 63 case LUA_OPBXOR: return intop(^, v1, v2);
64 case LUA_OPSHL: return luaV_shiftl(v1, v2); 64 case LUA_OPSHL: return luaV_shiftl(v1, v2);
65 case LUA_OPSHR: return luaV_shiftl(v1, -v2); 65 case LUA_OPSHR: return luaV_shiftr(v1, v2);
66 case LUA_OPUNM: return intop(-, 0, v1); 66 case LUA_OPUNM: return intop(-, 0, v1);
67 case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); 67 case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1);
68 default: lua_assert(0); return 0; 68 default: lua_assert(0); return 0;
diff --git a/src/3rdParty/lua/loslib.c b/src/3rdParty/lua/loslib.c
index 3e20d62..854dcf6 100644
--- a/src/3rdParty/lua/loslib.c
+++ b/src/3rdParty/lua/loslib.c
@@ -260,9 +260,7 @@ static int getfield (lua_State *L, const char *key, int d, int delta) {
260 res = d; 260 res = d;
261 } 261 }
262 else { 262 else {
263 /* unsigned avoids overflow when lua_Integer has 32 bits */ 263 if (!(res >= 0 ? res - delta <= INT_MAX : INT_MIN + delta <= res))
264 if (!(res >= 0 ? (lua_Unsigned)res <= (lua_Unsigned)INT_MAX + delta
265 : (lua_Integer)INT_MIN + delta <= res))
266 return luaL_error(L, "field '%s' is out-of-bound", key); 264 return luaL_error(L, "field '%s' is out-of-bound", key);
267 res -= delta; 265 res -= delta;
268 } 266 }
diff --git a/src/3rdParty/lua/ltablib.c b/src/3rdParty/lua/ltablib.c
index 868d78f..e6bc4d0 100644
--- a/src/3rdParty/lua/ltablib.c
+++ b/src/3rdParty/lua/ltablib.c
@@ -93,7 +93,7 @@ static int tremove (lua_State *L) {
93 lua_Integer pos = luaL_optinteger(L, 2, size); 93 lua_Integer pos = luaL_optinteger(L, 2, size);
94 if (pos != size) /* validate 'pos' if given */ 94 if (pos != size) /* validate 'pos' if given */
95 /* check whether 'pos' is in [1, size + 1] */ 95 /* check whether 'pos' is in [1, size + 1] */
96 luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 1, 96 luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 2,
97 "position out of bounds"); 97 "position out of bounds");
98 lua_geti(L, 1, pos); /* result = t[pos] */ 98 lua_geti(L, 1, pos); /* result = t[pos] */
99 for ( ; pos < size; pos++) { 99 for ( ; pos < size; pos++) {
diff --git a/src/3rdParty/lua/luaconf.h b/src/3rdParty/lua/luaconf.h
index fcc0018..e4650fb 100644
--- a/src/3rdParty/lua/luaconf.h
+++ b/src/3rdParty/lua/luaconf.h
@@ -747,14 +747,15 @@
747 747
748/* 748/*
749@@ LUA_IDSIZE gives the maximum size for the description of the source 749@@ LUA_IDSIZE gives the maximum size for the description of the source
750@@ of a function in debug information. 750** of a function in debug information.
751** CHANGE it if you want a different size. 751** CHANGE it if you want a different size.
752*/ 752*/
753#define LUA_IDSIZE 60 753#define LUA_IDSIZE 60
754 754
755 755
756/* 756/*
757@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. 757@@ LUAL_BUFFERSIZE is the initial buffer size used by the lauxlib
758** buffer system.
758*/ 759*/
759#define LUAL_BUFFERSIZE ((int)(16 * sizeof(void*) * sizeof(lua_Number))) 760#define LUAL_BUFFERSIZE ((int)(16 * sizeof(void*) * sizeof(lua_Number)))
760 761
diff --git a/src/3rdParty/lua/lutf8lib.c b/src/3rdParty/lua/lutf8lib.c
index e7bf098..3a5b9bc 100644
--- a/src/3rdParty/lua/lutf8lib.c
+++ b/src/3rdParty/lua/lutf8lib.c
@@ -25,6 +25,9 @@
25 25
26#define MAXUTF 0x7FFFFFFFu 26#define MAXUTF 0x7FFFFFFFu
27 27
28
29#define MSGInvalid "invalid UTF-8 code"
30
28/* 31/*
29** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits. 32** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits.
30*/ 33*/
@@ -35,7 +38,8 @@ typedef unsigned long utfint;
35#endif 38#endif
36 39
37 40
38#define iscont(p) ((*(p) & 0xC0) == 0x80) 41#define iscont(c) (((c) & 0xC0) == 0x80)
42#define iscontp(p) iscont(*(p))
39 43
40 44
41/* from strlib */ 45/* from strlib */
@@ -65,7 +69,7 @@ static const char *utf8_decode (const char *s, utfint *val, int strict) {
65 int count = 0; /* to count number of continuation bytes */ 69 int count = 0; /* to count number of continuation bytes */
66 for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */ 70 for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */
67 unsigned int cc = (unsigned char)s[++count]; /* read next byte */ 71 unsigned int cc = (unsigned char)s[++count]; /* read next byte */
68 if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ 72 if (!iscont(cc)) /* not a continuation byte? */
69 return NULL; /* invalid byte sequence */ 73 return NULL; /* invalid byte sequence */
70 res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ 74 res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */
71 } 75 }
@@ -140,7 +144,7 @@ static int codepoint (lua_State *L) {
140 utfint code; 144 utfint code;
141 s = utf8_decode(s, &code, !lax); 145 s = utf8_decode(s, &code, !lax);
142 if (s == NULL) 146 if (s == NULL)
143 return luaL_error(L, "invalid UTF-8 code"); 147 return luaL_error(L, MSGInvalid);
144 lua_pushinteger(L, code); 148 lua_pushinteger(L, code);
145 n++; 149 n++;
146 } 150 }
@@ -190,16 +194,16 @@ static int byteoffset (lua_State *L) {
190 "position out of bounds"); 194 "position out of bounds");
191 if (n == 0) { 195 if (n == 0) {
192 /* find beginning of current byte sequence */ 196 /* find beginning of current byte sequence */
193 while (posi > 0 && iscont(s + posi)) posi--; 197 while (posi > 0 && iscontp(s + posi)) posi--;
194 } 198 }
195 else { 199 else {
196 if (iscont(s + posi)) 200 if (iscontp(s + posi))
197 return luaL_error(L, "initial position is a continuation byte"); 201 return luaL_error(L, "initial position is a continuation byte");
198 if (n < 0) { 202 if (n < 0) {
199 while (n < 0 && posi > 0) { /* move back */ 203 while (n < 0 && posi > 0) { /* move back */
200 do { /* find beginning of previous character */ 204 do { /* find beginning of previous character */
201 posi--; 205 posi--;
202 } while (posi > 0 && iscont(s + posi)); 206 } while (posi > 0 && iscontp(s + posi));
203 n++; 207 n++;
204 } 208 }
205 } 209 }
@@ -208,7 +212,7 @@ static int byteoffset (lua_State *L) {
208 while (n > 0 && posi < (lua_Integer)len) { 212 while (n > 0 && posi < (lua_Integer)len) {
209 do { /* find beginning of next character */ 213 do { /* find beginning of next character */
210 posi++; 214 posi++;
211 } while (iscont(s + posi)); /* (cannot pass final '\0') */ 215 } while (iscontp(s + posi)); /* (cannot pass final '\0') */
212 n--; 216 n--;
213 } 217 }
214 } 218 }
@@ -226,15 +230,15 @@ static int iter_aux (lua_State *L, int strict) {
226 const char *s = luaL_checklstring(L, 1, &len); 230 const char *s = luaL_checklstring(L, 1, &len);
227 lua_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2); 231 lua_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2);
228 if (n < len) { 232 if (n < len) {
229 while (iscont(s + n)) n++; /* skip continuation bytes */ 233 while (iscontp(s + n)) n++; /* go to next character */
230 } 234 }
231 if (n >= len) /* (also handles original 'n' being negative) */ 235 if (n >= len) /* (also handles original 'n' being negative) */
232 return 0; /* no more codepoints */ 236 return 0; /* no more codepoints */
233 else { 237 else {
234 utfint code; 238 utfint code;
235 const char *next = utf8_decode(s + n, &code, strict); 239 const char *next = utf8_decode(s + n, &code, strict);
236 if (next == NULL) 240 if (next == NULL || iscontp(next))
237 return luaL_error(L, "invalid UTF-8 code"); 241 return luaL_error(L, MSGInvalid);
238 lua_pushinteger(L, n + 1); 242 lua_pushinteger(L, n + 1);
239 lua_pushinteger(L, code); 243 lua_pushinteger(L, code);
240 return 2; 244 return 2;
@@ -253,7 +257,8 @@ static int iter_auxlax (lua_State *L) {
253 257
254static int iter_codes (lua_State *L) { 258static int iter_codes (lua_State *L) {
255 int lax = lua_toboolean(L, 2); 259 int lax = lua_toboolean(L, 2);
256 luaL_checkstring(L, 1); 260 const char *s = luaL_checkstring(L, 1);
261 luaL_argcheck(L, !iscontp(s), 1, MSGInvalid);
257 lua_pushcfunction(L, lax ? iter_auxlax : iter_auxstrict); 262 lua_pushcfunction(L, lax ? iter_auxlax : iter_auxstrict);
258 lua_pushvalue(L, 1); 263 lua_pushvalue(L, 1);
259 lua_pushinteger(L, 0); 264 lua_pushinteger(L, 0);
diff --git a/src/3rdParty/lua/lvm.c b/src/3rdParty/lua/lvm.c
index 614df05..73a19ba 100644
--- a/src/3rdParty/lua/lvm.c
+++ b/src/3rdParty/lua/lvm.c
@@ -765,12 +765,10 @@ lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) {
765/* number of bits in an integer */ 765/* number of bits in an integer */
766#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT) 766#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT)
767 767
768
768/* 769/*
769** Shift left operation. (Shift right just negates 'y'.) 770** Shift left operation. (Shift right just negates 'y'.)
770*/ 771*/
771#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y))
772
773
774lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { 772lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) {
775 if (y < 0) { /* shift right? */ 773 if (y < 0) { /* shift right? */
776 if (y <= -NBITS) return 0; 774 if (y <= -NBITS) return 0;
diff --git a/src/3rdParty/lua/lvm.h b/src/3rdParty/lua/lvm.h
index 1bc16f3..dba1ad2 100644
--- a/src/3rdParty/lua/lvm.h
+++ b/src/3rdParty/lua/lvm.h
@@ -110,6 +110,11 @@ typedef enum {
110 luaC_barrierback(L, gcvalue(t), v); } 110 luaC_barrierback(L, gcvalue(t), v); }
111 111
112 112
113/*
114** Shift right is the same as shift left with a negative 'y'
115*/
116#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y))
117
113 118
114 119
115LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); 120LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 1712e8a..ed963be 100755
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -828,7 +828,6 @@ AST_NODE(Statement)
828 Import_t, While_t, Repeat_t, For_t, ForEach_t, 828 Import_t, While_t, Repeat_t, For_t, ForEach_t,
829 Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t, 829 Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t,
830 BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t, 830 BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t,
831 BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t,
832 Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t 831 Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t
833 > content; 832 > content;
834 ast_ptr<false, statement_appendix_t> appendix; 833 ast_ptr<false, statement_appendix_t> appendix;
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 1d949fe..672f2d4 100755..100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -14,6 +14,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
14#include <unordered_map> 14#include <unordered_map>
15#include <unordered_set> 15#include <unordered_set>
16#include <vector> 16#include <vector>
17#include <optional>
17 18
18#include "yuescript/yue_compiler.h" 19#include "yuescript/yue_compiler.h"
19#include "yuescript/yue_parser.h" 20#include "yuescript/yue_parser.h"
@@ -59,7 +60,7 @@ namespace yue {
59 60
60typedef std::list<std::string> str_list; 61typedef std::list<std::string> str_list;
61 62
62const std::string_view version = "0.15.3"sv; 63const std::string_view version = "0.15.4"sv;
63const std::string_view extension = "yue"sv; 64const std::string_view extension = "yue"sv;
64 65
65class YueCompilerImpl { 66class YueCompilerImpl {
@@ -146,11 +147,30 @@ public:
146 str_list out; 147 str_list out;
147 pushScope(); 148 pushScope();
148 _enableReturn.push(_info.moduleName.empty()); 149 _enableReturn.push(_info.moduleName.empty());
150 _gotoScopes.push(0);
151 _gotoScope = 1;
149 _varArgs.push({true, false}); 152 _varArgs.push({true, false});
150 transformBlock(block, out, 153 transformBlock(block, out,
151 config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common, 154 config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common,
152 nullptr, true); 155 nullptr, true);
153 popScope(); 156 popScope();
157 if (!gotos.empty()) {
158 for (const auto& gotoNode : gotos) {
159 bool noLabel = true;
160 BLOCK_START
161 BREAK_IF(static_cast<int>(_labels.size()) <= gotoNode.scope);
162 BREAK_IF(_labels[gotoNode.scope] == std::nullopt);
163 const auto& scope = _labels[gotoNode.scope].value();
164 auto it = scope.find(gotoNode.label);
165 BREAK_IF(it == scope.end());
166 BREAK_IF(gotoNode.level < it->second.level);
167 noLabel = false;
168 BLOCK_END
169 if (noLabel) {
170 throw std::logic_error(_info.errorMessage("no visible label '"s + gotoNode.label + "' for <goto>"s, gotoNode.ptr->label));
171 }
172 }
173 }
154 if (config.lintGlobalVariable) { 174 if (config.lintGlobalVariable) {
155 globals = std::make_unique<GlobalVars>(); 175 globals = std::make_unique<GlobalVars>();
156 for (const auto& var : _globals) { 176 for (const auto& var : _globals) {
@@ -256,6 +276,20 @@ private:
256 std::ostringstream _buf; 276 std::ostringstream _buf;
257 std::ostringstream _joinBuf; 277 std::ostringstream _joinBuf;
258 const std::string _newLine = "\n"; 278 const std::string _newLine = "\n";
279 int _gotoScope = 0;
280 std::stack<int> _gotoScopes;
281 struct LabelNode {
282 int line;
283 int level;
284 };
285 std::vector<std::optional<std::unordered_map<std::string, LabelNode>>> _labels;
286 struct GotoNode {
287 ast_ptr<true, Goto_t> ptr;
288 std::string label;
289 int scope;
290 int level;
291 };
292 std::list<GotoNode> gotos;
259 293
260 enum class LocalMode { 294 enum class LocalMode {
261 None = 0, 295 None = 0,
@@ -457,13 +491,30 @@ private:
457 std::string getUnusedName(std::string_view name) const { 491 std::string getUnusedName(std::string_view name) const {
458 int index = 0; 492 int index = 0;
459 std::string newName; 493 std::string newName;
494 std::string nameStr(name);
460 do { 495 do {
461 newName = std::string(name) + std::to_string(index); 496 newName = nameStr + std::to_string(index);
462 index++; 497 index++;
463 } while (isLocal(newName)); 498 } while (isLocal(newName));
464 return newName; 499 return newName;
465 } 500 }
466 501
502 std::string getUnusedLabel(std::string_view label) const {
503 int scopeIndex = _gotoScopes.top();
504 if (static_cast<int>(_labels.size()) <= scopeIndex || _labels[scopeIndex] == std::nullopt) {
505 return std::string(label) + '0';
506 }
507 auto& scope = _labels[scopeIndex].value();
508 int index = 0;
509 std::string newLabel;
510 std::string labelStr(label);
511 do {
512 newLabel = labelStr + std::to_string(index);
513 index++;
514 } while (scope.find(newLabel) != scope.end());
515 return newLabel;
516 }
517
467 std::string transformCondExp(Exp_t* cond, bool unless) { 518 std::string transformCondExp(Exp_t* cond, bool unless) {
468 str_list tmp; 519 str_list tmp;
469 if (unless) { 520 if (unless) {
@@ -975,6 +1026,17 @@ private:
975 return false; 1026 return false;
976 } 1027 }
977 1028
1029 void pushFunctionScope() {
1030 _enableReturn.push(true);
1031 _gotoScopes.push(_gotoScope);
1032 _gotoScope++;
1033 }
1034
1035 void popFunctionScope() {
1036 _enableReturn.pop();
1037 _gotoScopes.pop();
1038 }
1039
978 void pushAnonVarArg() { 1040 void pushAnonVarArg() {
979 if (!_varArgs.empty() && _varArgs.top().hasVar) { 1041 if (!_varArgs.empty() && _varArgs.top().hasVar) {
980 _varArgs.push({true, false}); 1042 _varArgs.push({true, false});
@@ -2642,7 +2704,7 @@ private:
2642 str_list temp; 2704 str_list temp;
2643 std::string* funcStart = nullptr; 2705 std::string* funcStart = nullptr;
2644 if (usage == ExpUsage::Closure) { 2706 if (usage == ExpUsage::Closure) {
2645 _enableReturn.push(true); 2707 pushFunctionScope();
2646 pushAnonVarArg(); 2708 pushAnonVarArg();
2647 funcStart = &temp.emplace_back(); 2709 funcStart = &temp.emplace_back();
2648 pushScope(); 2710 pushScope();
@@ -2765,7 +2827,7 @@ private:
2765 *funcStart = anonFuncStart() + nll(nodes.front()); 2827 *funcStart = anonFuncStart() + nll(nodes.front());
2766 temp.push_back(indent() + anonFuncEnd()); 2828 temp.push_back(indent() + anonFuncEnd());
2767 popAnonVarArg(); 2829 popAnonVarArg();
2768 _enableReturn.pop(); 2830 popFunctionScope();
2769 } 2831 }
2770 out.push_back(join(temp)); 2832 out.push_back(join(temp));
2771 } 2833 }
@@ -2928,7 +2990,7 @@ private:
2928 } 2990 }
2929 std::string* funcStart = nullptr; 2991 std::string* funcStart = nullptr;
2930 if (usage == ExpUsage::Closure) { 2992 if (usage == ExpUsage::Closure) {
2931 _enableReturn.push(true); 2993 pushFunctionScope();
2932 pushAnonVarArg(); 2994 pushAnonVarArg();
2933 funcStart = &temp.emplace_back(); 2995 funcStart = &temp.emplace_back();
2934 pushScope(); 2996 pushScope();
@@ -2974,7 +3036,7 @@ private:
2974 *funcStart = anonFuncStart() + nll(x); 3036 *funcStart = anonFuncStart() + nll(x);
2975 temp.push_back(indent() + anonFuncEnd()); 3037 temp.push_back(indent() + anonFuncEnd());
2976 popAnonVarArg(); 3038 popAnonVarArg();
2977 _enableReturn.pop(); 3039 popFunctionScope();
2978 } 3040 }
2979 break; 3041 break;
2980 } 3042 }
@@ -3091,7 +3153,7 @@ private:
3091 } 3153 }
3092 3154
3093 void transformFunLit(FunLit_t* funLit, str_list& out) { 3155 void transformFunLit(FunLit_t* funLit, str_list& out) {
3094 _enableReturn.push(true); 3156 pushFunctionScope();
3095 _varArgs.push({false, false}); 3157 _varArgs.push({false, false});
3096 bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv; 3158 bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv;
3097 pushScope(); 3159 pushScope();
@@ -3142,7 +3204,7 @@ private:
3142 } 3204 }
3143 } 3205 }
3144 out.push_back(clearBuf()); 3206 out.push_back(clearBuf());
3145 _enableReturn.pop(); 3207 popFunctionScope();
3146 _varArgs.pop(); 3208 _varArgs.pop();
3147 } 3209 }
3148 3210
@@ -3979,7 +4041,7 @@ private:
3979 str_list temp; 4041 str_list temp;
3980 std::string* funcStart = nullptr; 4042 std::string* funcStart = nullptr;
3981 if (usage == ExpUsage::Closure) { 4043 if (usage == ExpUsage::Closure) {
3982 _enableReturn.push(true); 4044 pushFunctionScope();
3983 pushAnonVarArg(); 4045 pushAnonVarArg();
3984 funcStart = &temp.emplace_back(); 4046 funcStart = &temp.emplace_back();
3985 pushScope(); 4047 pushScope();
@@ -4122,7 +4184,7 @@ private:
4122 *funcStart = anonFuncStart() + nll(x); 4184 *funcStart = anonFuncStart() + nll(x);
4123 temp.push_back(indent() + anonFuncEnd()); 4185 temp.push_back(indent() + anonFuncEnd());
4124 popAnonVarArg(); 4186 popAnonVarArg();
4125 _enableReturn.pop(); 4187 popFunctionScope();
4126 break; 4188 break;
4127 default: 4189 default:
4128 break; 4190 break;
@@ -4148,7 +4210,7 @@ private:
4148 pushScope(); 4210 pushScope();
4149 break; 4211 break;
4150 case ExpUsage::Closure: 4212 case ExpUsage::Closure:
4151 _enableReturn.push(true); 4213 pushFunctionScope();
4152 pushAnonVarArg(); 4214 pushAnonVarArg();
4153 funcStart = &temp.emplace_back(); 4215 funcStart = &temp.emplace_back();
4154 pushScope(); 4216 pushScope();
@@ -4226,7 +4288,7 @@ private:
4226 *funcStart = anonFuncStart() + nll(x); 4288 *funcStart = anonFuncStart() + nll(x);
4227 temp.push_back(indent() + anonFuncEnd()); 4289 temp.push_back(indent() + anonFuncEnd());
4228 popAnonVarArg(); 4290 popAnonVarArg();
4229 _enableReturn.pop(); 4291 popFunctionScope();
4230 break; 4292 break;
4231 default: 4293 default:
4232 break; 4294 break;
@@ -4283,7 +4345,7 @@ private:
4283 str_list temp; 4345 str_list temp;
4284 std::string* funcStart = nullptr; 4346 std::string* funcStart = nullptr;
4285 if (usage == ExpUsage::Closure) { 4347 if (usage == ExpUsage::Closure) {
4286 _enableReturn.push(true); 4348 pushFunctionScope();
4287 pushAnonVarArg(); 4349 pushAnonVarArg();
4288 funcStart = &temp.emplace_back(); 4350 funcStart = &temp.emplace_back();
4289 pushScope(); 4351 pushScope();
@@ -4326,7 +4388,7 @@ private:
4326 *funcStart = anonFuncStart() + nll(x); 4388 *funcStart = anonFuncStart() + nll(x);
4327 temp.push_back(indent() + anonFuncEnd()); 4389 temp.push_back(indent() + anonFuncEnd());
4328 popAnonVarArg(); 4390 popAnonVarArg();
4329 _enableReturn.pop(); 4391 popFunctionScope();
4330 break; 4392 break;
4331 } 4393 }
4332 case ExpUsage::Return: { 4394 case ExpUsage::Return: {
@@ -5052,7 +5114,7 @@ private:
5052 auto x = values.front(); 5114 auto x = values.front();
5053 switch (usage) { 5115 switch (usage) {
5054 case ExpUsage::Closure: 5116 case ExpUsage::Closure:
5055 _enableReturn.push(true); 5117 pushFunctionScope();
5056 pushAnonVarArg(); 5118 pushAnonVarArg();
5057 pushScope(); 5119 pushScope();
5058 break; 5120 break;
@@ -5255,7 +5317,7 @@ private:
5255 out.back().insert(0, anonFuncStart() + nll(x)); 5317 out.back().insert(0, anonFuncStart() + nll(x));
5256 out.back().append(indent() + anonFuncEnd()); 5318 out.back().append(indent() + anonFuncEnd());
5257 popAnonVarArg(); 5319 popAnonVarArg();
5258 _enableReturn.pop(); 5320 popFunctionScope();
5259 break; 5321 break;
5260 } 5322 }
5261 case ExpUsage::Assignment: { 5323 case ExpUsage::Assignment: {
@@ -5447,7 +5509,7 @@ private:
5447 auto x = comp; 5509 auto x = comp;
5448 switch (usage) { 5510 switch (usage) {
5449 case ExpUsage::Closure: 5511 case ExpUsage::Closure:
5450 _enableReturn.push(true); 5512 pushFunctionScope();
5451 pushAnonVarArg(); 5513 pushAnonVarArg();
5452 pushScope(); 5514 pushScope();
5453 break; 5515 break;
@@ -5511,7 +5573,7 @@ private:
5511 out.back().insert(0, anonFuncStart() + nll(comp)); 5573 out.back().insert(0, anonFuncStart() + nll(comp));
5512 out.back().append(indent() + anonFuncEnd()); 5574 out.back().append(indent() + anonFuncEnd());
5513 popAnonVarArg(); 5575 popAnonVarArg();
5514 _enableReturn.pop(); 5576 popFunctionScope();
5515 break; 5577 break;
5516 } 5578 }
5517 case ExpUsage::Assignment: { 5579 case ExpUsage::Assignment: {
@@ -5804,44 +5866,80 @@ private:
5804 str_list temp; 5866 str_list temp;
5805 bool extraDo = false; 5867 bool extraDo = false;
5806 bool withContinue = hasContinueStatement(body); 5868 bool withContinue = hasContinueStatement(body);
5869 int target = getLuaTarget(body);
5870 std::string extraLabel;
5807 if (withContinue) { 5871 if (withContinue) {
5808 if (auto block = ast_cast<Block_t>(body)) { 5872 if (target < 502) {
5809 if (!block->statements.empty()) { 5873 if (auto block = ast_cast<Block_t>(body)) {
5810 auto stmt = static_cast<Statement_t*>(block->statements.back()); 5874 if (!block->statements.empty()) {
5811 if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { 5875 auto stmt = static_cast<Statement_t*>(block->statements.back());
5812 extraDo = _parser.toString(breakLoop) == "break"sv; 5876 if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) {
5877 extraDo = _parser.toString(breakLoop) == "break"sv;
5878 }
5813 } 5879 }
5814 } 5880 }
5815 } 5881 auto continueVar = getUnusedName("_continue_"sv);
5816 auto continueVar = getUnusedName("_continue_"sv); 5882 addToScope(continueVar);
5817 addToScope(continueVar); 5883 _continueVars.push({continueVar, nullptr});
5818 _continueVars.push({continueVar, nullptr}); 5884 _buf << indent() << "local "sv << continueVar << " = false"sv << nll(body);
5819 _buf << indent() << "local "sv << continueVar << " = false"sv << nll(body); 5885 _buf << indent() << "repeat"sv << nll(body);
5820 _buf << indent() << "repeat"sv << nll(body);
5821 pushScope();
5822 if (extraDo) {
5823 _buf << indent() << "do"sv << nll(body);
5824 pushScope(); 5886 pushScope();
5887 if (extraDo) {
5888 _buf << indent() << "do"sv << nll(body);
5889 pushScope();
5890 }
5891 temp.push_back(clearBuf());
5892 } else {
5893 auto continueLabel = getUnusedLabel("_continue_"sv);
5894 _continueVars.push({continueLabel, nullptr});
5895 transformLabel(toAst<Label_t>("::"s + _continueVars.top().var + "::"s, body), temp);
5896 extraLabel = temp.back();
5897 temp.pop_back();
5898 }
5899 if (auto block = ast_cast<Block_t>(body); body && !block->statements.empty()) {
5900 auto last = static_cast<Statement_t*>(block->statements.back());
5901 if (last->content.is<Return_t>()) {
5902 auto doNode = last->new_ptr<Do_t>();
5903 auto newBody = last->new_ptr<Body_t>();
5904 auto newStmt = last->new_ptr<Statement_t>();
5905 newStmt->content.set(last->content);
5906 newBody->content.set(newStmt);
5907 doNode->body.set(newBody);
5908 auto simpleValue = last->new_ptr<SimpleValue_t>();
5909 simpleValue->value.set(doNode);
5910 auto expList = last->new_ptr<ExpList_t>();
5911 expList->exprs.push_back(newExp(simpleValue, last));
5912 auto expListAssign = last->new_ptr<ExpListAssign_t>();
5913 expListAssign->expList.set(expList);
5914 last->content.set(expListAssign);
5915 }
5825 } 5916 }
5826 temp.push_back(clearBuf());
5827 } 5917 }
5828 transform_plain_body(body, temp, usage, assignList); 5918 transform_plain_body(body, temp, usage, assignList);
5829 if (withContinue) { 5919 if (withContinue) {
5830 if (extraDo) { 5920 if (target < 502) {
5921 if (extraDo) {
5922 popScope();
5923 _buf << indent() << "end"sv << nll(body);
5924 }
5925 if (!appendContent.empty()) {
5926 _buf << indent() << appendContent;
5927 }
5928 _buf << indent() << _continueVars.top().var << " = true"sv << nll(body);
5831 popScope(); 5929 popScope();
5832 _buf << indent() << "end"sv << nll(body); 5930 _buf << indent() << "until true"sv << nlr(body);
5833 } 5931 _buf << indent() << "if not "sv << _continueVars.top().var << " then"sv << nlr(body);
5834 if (!appendContent.empty()) { 5932 _buf << indent(1) << "break"sv << nlr(body);
5835 _buf << indent() << appendContent; 5933 _buf << indent() << "end"sv << nlr(body);
5934 temp.push_back(clearBuf());
5935 _continueVars.pop();
5936 } else {
5937 if (!appendContent.empty()) {
5938 temp.push_back(indent() + appendContent);
5939 }
5940 temp.push_back(extraLabel);
5941 _continueVars.pop();
5836 } 5942 }
5837 _buf << indent() << _continueVars.top().var << " = true"sv << nll(body);
5838 popScope();
5839 _buf << indent() << "until true"sv << nlr(body);
5840 _buf << indent() << "if not "sv << _continueVars.top().var << " then"sv << nlr(body);
5841 _buf << indent(1) << "break"sv << nlr(body);
5842 _buf << indent() << "end"sv << nlr(body);
5843 temp.push_back(clearBuf());
5844 _continueVars.pop();
5845 } else if (!appendContent.empty()) { 5943 } else if (!appendContent.empty()) {
5846 temp.back().append(indent() + appendContent); 5944 temp.back().append(indent() + appendContent);
5847 } 5945 }
@@ -5854,56 +5952,67 @@ private:
5854 auto body = repeatNode->body->content.get(); 5952 auto body = repeatNode->body->content.get();
5855 bool withContinue = hasContinueStatement(body); 5953 bool withContinue = hasContinueStatement(body);
5856 std::string conditionVar; 5954 std::string conditionVar;
5955 std::string extraLabel;
5956 ast_ptr<false, ExpListAssign_t> condAssign;
5957 int target = getLuaTarget(repeatNode);
5857 if (withContinue) { 5958 if (withContinue) {
5858 if (auto block = ast_cast<Block_t>(body)) { 5959 if (target < 502) {
5859 if (!block->statements.empty()) { 5960 if (auto block = ast_cast<Block_t>(body)) {
5860 auto stmt = static_cast<Statement_t*>(block->statements.back()); 5961 if (!block->statements.empty()) {
5861 if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { 5962 auto stmt = static_cast<Statement_t*>(block->statements.back());
5862 extraDo = _parser.toString(breakLoop) == "break"sv; 5963 if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) {
5964 extraDo = _parser.toString(breakLoop) == "break"sv;
5965 }
5863 } 5966 }
5864 } 5967 }
5865 } 5968 conditionVar = getUnusedName("_cond_");
5866 conditionVar = getUnusedName("_cond_"); 5969 forceAddToScope(conditionVar);
5867 forceAddToScope(conditionVar); 5970 auto continueVar = getUnusedName("_continue_"sv);
5868 auto continueVar = getUnusedName("_continue_"sv); 5971 forceAddToScope(continueVar);
5869 forceAddToScope(continueVar); 5972 {
5870 { 5973 auto assignment = toAst<ExpListAssign_t>(conditionVar + "=nil"s, repeatNode->condition);
5871 auto assignment = toAst<ExpListAssign_t>(conditionVar + "=nil"s, repeatNode->condition); 5974 auto assign = assignment->action.to<Assign_t>();
5872 auto assign = assignment->action.to<Assign_t>(); 5975 assign->values.clear();
5873 assign->values.clear(); 5976 assign->values.push_back(repeatNode->condition);
5874 assign->values.push_back(repeatNode->condition); 5977 _continueVars.push({continueVar, assignment.get()});
5875 _continueVars.push({continueVar, assignment.get()}); 5978 }
5876 } 5979 _buf << indent() << "local "sv << conditionVar << " = false"sv << nll(body);
5877 _buf << indent() << "local "sv << conditionVar << " = false"sv << nll(body); 5980 _buf << indent() << "local "sv << continueVar << " = false"sv << nll(body);
5878 _buf << indent() << "local "sv << continueVar << " = false"sv << nll(body); 5981 _buf << indent() << "repeat"sv << nll(body);
5879 _buf << indent() << "repeat"sv << nll(body);
5880 pushScope();
5881 if (extraDo) {
5882 _buf << indent() << "do"sv << nll(body);
5883 pushScope(); 5982 pushScope();
5983 if (extraDo) {
5984 _buf << indent() << "do"sv << nll(body);
5985 pushScope();
5986 }
5987 temp.push_back(clearBuf());
5988 } else {
5989 auto continueLabel = getUnusedLabel("_continue_"sv);
5990 _continueVars.push({continueLabel, nullptr});
5991 transformLabel(toAst<Label_t>("::"s + _continueVars.top().var + "::"s, body), temp);
5992 extraLabel = temp.back();
5993 temp.pop_back();
5884 } 5994 }
5885 temp.push_back(clearBuf());
5886 } 5995 }
5887 transform_plain_body(body, temp, ExpUsage::Common); 5996 transform_plain_body(body, temp, ExpUsage::Common);
5888 if (withContinue) { 5997 if (withContinue) {
5889 { 5998 if (target < 502) {
5890 transformAssignment(_continueVars.top().condAssign, temp); 5999 transformAssignment(_continueVars.top().condAssign, temp);
5891 auto assignCond = std::move(temp.back()); 6000 if (extraDo) {
5892 temp.pop_back(); 6001 popScope();
5893 temp.back().append(assignCond); 6002 _buf << indent() << "end"sv << nll(body);
5894 } 6003 }
5895 if (extraDo) { 6004 _buf << indent() << _continueVars.top().var << " = true"sv << nll(body);
5896 popScope(); 6005 popScope();
5897 _buf << indent() << "end"sv << nll(body); 6006 _buf << indent() << "until true"sv << nlr(body);
6007 _buf << indent() << "if not "sv << _continueVars.top().var << " then"sv << nlr(body);
6008 _buf << indent(1) << "break"sv << nlr(body);
6009 _buf << indent() << "end"sv << nlr(body);
6010 temp.push_back(clearBuf());
6011 _continueVars.pop();
6012 } else {
6013 temp.push_back(extraLabel);
6014 _continueVars.pop();
5898 } 6015 }
5899 _buf << indent() << _continueVars.top().var << " = true"sv << nll(body);
5900 popScope();
5901 _buf << indent() << "until true"sv << nlr(body);
5902 _buf << indent() << "if not "sv << _continueVars.top().var << " then"sv << nlr(body);
5903 _buf << indent(1) << "break"sv << nlr(body);
5904 _buf << indent() << "end"sv << nlr(body);
5905 temp.push_back(clearBuf());
5906 _continueVars.pop();
5907 } 6016 }
5908 out.push_back(join(temp)); 6017 out.push_back(join(temp));
5909 return conditionVar; 6018 return conditionVar;
@@ -5937,7 +6046,7 @@ private:
5937 6046
5938 void transformForClosure(For_t* forNode, str_list& out) { 6047 void transformForClosure(For_t* forNode, str_list& out) {
5939 str_list temp; 6048 str_list temp;
5940 _enableReturn.push(true); 6049 pushFunctionScope();
5941 pushAnonVarArg(); 6050 pushAnonVarArg();
5942 std::string& funcStart = temp.emplace_back(); 6051 std::string& funcStart = temp.emplace_back();
5943 pushScope(); 6052 pushScope();
@@ -5947,7 +6056,7 @@ private:
5947 funcStart = anonFuncStart() + nll(forNode); 6056 funcStart = anonFuncStart() + nll(forNode);
5948 temp.push_back(indent() + anonFuncEnd()); 6057 temp.push_back(indent() + anonFuncEnd());
5949 popAnonVarArg(); 6058 popAnonVarArg();
5950 _enableReturn.pop(); 6059 popFunctionScope();
5951 out.push_back(join(temp)); 6060 out.push_back(join(temp));
5952 } 6061 }
5953 6062
@@ -6026,7 +6135,7 @@ private:
6026 6135
6027 void transformForEachClosure(ForEach_t* forEach, str_list& out) { 6136 void transformForEachClosure(ForEach_t* forEach, str_list& out) {
6028 str_list temp; 6137 str_list temp;
6029 _enableReturn.push(true); 6138 pushFunctionScope();
6030 pushAnonVarArg(); 6139 pushAnonVarArg();
6031 std::string& funcStart = temp.emplace_back(); 6140 std::string& funcStart = temp.emplace_back();
6032 pushScope(); 6141 pushScope();
@@ -6036,7 +6145,7 @@ private:
6036 funcStart = anonFuncStart() + nll(forEach); 6145 funcStart = anonFuncStart() + nll(forEach);
6037 temp.push_back(indent() + anonFuncEnd()); 6146 temp.push_back(indent() + anonFuncEnd());
6038 popAnonVarArg(); 6147 popAnonVarArg();
6039 _enableReturn.pop(); 6148 popFunctionScope();
6040 out.push_back(join(temp)); 6149 out.push_back(join(temp));
6041 } 6150 }
6042 6151
@@ -6202,7 +6311,7 @@ private:
6202 6311
6203 void transformClassDeclClosure(ClassDecl_t* classDecl, str_list& out) { 6312 void transformClassDeclClosure(ClassDecl_t* classDecl, str_list& out) {
6204 str_list temp; 6313 str_list temp;
6205 _enableReturn.push(true); 6314 pushFunctionScope();
6206 pushAnonVarArg(); 6315 pushAnonVarArg();
6207 std::string& funcStart = temp.emplace_back(); 6316 std::string& funcStart = temp.emplace_back();
6208 pushScope(); 6317 pushScope();
@@ -6211,7 +6320,7 @@ private:
6211 funcStart = anonFuncStart() + nll(classDecl); 6320 funcStart = anonFuncStart() + nll(classDecl);
6212 temp.push_back(indent() + anonFuncEnd()); 6321 temp.push_back(indent() + anonFuncEnd());
6213 popAnonVarArg(); 6322 popAnonVarArg();
6214 _enableReturn.pop(); 6323 popFunctionScope();
6215 out.push_back(join(temp)); 6324 out.push_back(join(temp));
6216 } 6325 }
6217 6326
@@ -6611,7 +6720,7 @@ private:
6611 6720
6612 void transformWithClosure(With_t* with, str_list& out) { 6721 void transformWithClosure(With_t* with, str_list& out) {
6613 str_list temp; 6722 str_list temp;
6614 _enableReturn.push(true); 6723 pushFunctionScope();
6615 pushAnonVarArg(); 6724 pushAnonVarArg();
6616 std::string& funcStart = temp.emplace_back(); 6725 std::string& funcStart = temp.emplace_back();
6617 pushScope(); 6726 pushScope();
@@ -6620,7 +6729,7 @@ private:
6620 funcStart = anonFuncStart() + nll(with); 6729 funcStart = anonFuncStart() + nll(with);
6621 temp.push_back(indent() + anonFuncEnd()); 6730 temp.push_back(indent() + anonFuncEnd());
6622 popAnonVarArg(); 6731 popAnonVarArg();
6623 _enableReturn.pop(); 6732 popFunctionScope();
6624 out.push_back(join(temp)); 6733 out.push_back(join(temp));
6625 } 6734 }
6626 6735
@@ -6918,7 +7027,7 @@ private:
6918 void transformTblComprehension(TblComprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 7027 void transformTblComprehension(TblComprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
6919 switch (usage) { 7028 switch (usage) {
6920 case ExpUsage::Closure: 7029 case ExpUsage::Closure:
6921 _enableReturn.push(true); 7030 pushFunctionScope();
6922 pushAnonVarArg(); 7031 pushAnonVarArg();
6923 pushScope(); 7032 pushScope();
6924 break; 7033 break;
@@ -6980,7 +7089,7 @@ private:
6980 out.back().insert(0, anonFuncStart() + nll(comp)); 7089 out.back().insert(0, anonFuncStart() + nll(comp));
6981 out.back().append(indent() + anonFuncEnd()); 7090 out.back().append(indent() + anonFuncEnd());
6982 popAnonVarArg(); 7091 popAnonVarArg();
6983 _enableReturn.pop(); 7092 popFunctionScope();
6984 break; 7093 break;
6985 case ExpUsage::Assignment: { 7094 case ExpUsage::Assignment: {
6986 out.push_back(clearBuf()); 7095 out.push_back(clearBuf());
@@ -7025,7 +7134,7 @@ private:
7025 str_list temp; 7134 str_list temp;
7026 std::string* funcStart = nullptr; 7135 std::string* funcStart = nullptr;
7027 if (usage == ExpUsage::Closure) { 7136 if (usage == ExpUsage::Closure) {
7028 _enableReturn.push(true); 7137 pushFunctionScope();
7029 pushAnonVarArg(); 7138 pushAnonVarArg();
7030 funcStart = &temp.emplace_back(); 7139 funcStart = &temp.emplace_back();
7031 } else { 7140 } else {
@@ -7038,7 +7147,7 @@ private:
7038 *funcStart = anonFuncStart() + nll(doNode); 7147 *funcStart = anonFuncStart() + nll(doNode);
7039 temp.push_back(indent() + anonFuncEnd()); 7148 temp.push_back(indent() + anonFuncEnd());
7040 popAnonVarArg(); 7149 popAnonVarArg();
7041 _enableReturn.pop(); 7150 popFunctionScope();
7042 } else { 7151 } else {
7043 temp.push_back(indent() + "end"s + nlr(doNode)); 7152 temp.push_back(indent() + "end"s + nlr(doNode));
7044 } 7153 }
@@ -7445,7 +7554,7 @@ private:
7445 void transformWhileClosure(While_t* whileNode, str_list& out) { 7554 void transformWhileClosure(While_t* whileNode, str_list& out) {
7446 auto x = whileNode; 7555 auto x = whileNode;
7447 str_list temp; 7556 str_list temp;
7448 _enableReturn.push(true); 7557 pushFunctionScope();
7449 pushAnonVarArg(); 7558 pushAnonVarArg();
7450 std::string& funcStart = temp.emplace_back(); 7559 std::string& funcStart = temp.emplace_back();
7451 pushScope(); 7560 pushScope();
@@ -7469,7 +7578,7 @@ private:
7469 funcStart = anonFuncStart() + nll(whileNode); 7578 funcStart = anonFuncStart() + nll(whileNode);
7470 temp.push_back(indent() + anonFuncEnd()); 7579 temp.push_back(indent() + anonFuncEnd());
7471 popAnonVarArg(); 7580 popAnonVarArg();
7472 _enableReturn.pop(); 7581 popFunctionScope();
7473 out.push_back(join(temp)); 7582 out.push_back(join(temp));
7474 } 7583 }
7475 7584
@@ -7507,7 +7616,7 @@ private:
7507 str_list temp; 7616 str_list temp;
7508 std::string* funcStart = nullptr; 7617 std::string* funcStart = nullptr;
7509 if (usage == ExpUsage::Closure) { 7618 if (usage == ExpUsage::Closure) {
7510 _enableReturn.push(true); 7619 pushFunctionScope();
7511 pushAnonVarArg(); 7620 pushAnonVarArg();
7512 funcStart = &temp.emplace_back(); 7621 funcStart = &temp.emplace_back();
7513 pushScope(); 7622 pushScope();
@@ -7631,7 +7740,7 @@ private:
7631 } 7740 }
7632 temp.push_back(indent() + "end"s + nlr(switchNode)); 7741 temp.push_back(indent() + "end"s + nlr(switchNode));
7633 if (usage == ExpUsage::Closure) { 7742 if (usage == ExpUsage::Closure) {
7634 _enableReturn.pop(); 7743 popFunctionScope();
7635 popScope(); 7744 popScope();
7636 *funcStart = anonFuncStart() + nll(switchNode); 7745 *funcStart = anonFuncStart() + nll(switchNode);
7637 temp.push_back(indent() + anonFuncEnd()); 7746 temp.push_back(indent() + anonFuncEnd());
@@ -7798,29 +7907,52 @@ private:
7798 return; 7907 return;
7799 } 7908 }
7800 if (_continueVars.empty()) throw std::logic_error(_info.errorMessage("continue is not inside a loop"sv, breakLoop)); 7909 if (_continueVars.empty()) throw std::logic_error(_info.errorMessage("continue is not inside a loop"sv, breakLoop));
7910 str_list temp;
7801 auto& item = _continueVars.top(); 7911 auto& item = _continueVars.top();
7802 if (item.condAssign) { 7912 if (item.condAssign) {
7803 str_list temp;
7804 transformAssignment(item.condAssign, temp); 7913 transformAssignment(item.condAssign, temp);
7805 _buf << temp.back();
7806 } 7914 }
7807 _buf << indent() << item.var << " = true"sv << nll(breakLoop); 7915 if (getLuaTarget(breakLoop) < 502) {
7808 _buf << indent() << "break"sv << nll(breakLoop); 7916 if (!temp.empty()) {
7809 out.push_back(clearBuf()); 7917 _buf << temp.back();
7918 }
7919 _buf << indent() << item.var << " = true"sv << nll(breakLoop);
7920 _buf << indent() << "break"sv << nll(breakLoop);
7921 out.push_back(clearBuf());
7922 } else {
7923 transformGoto(toAst<Goto_t>("goto "s + item.var, breakLoop), temp);
7924 out.push_back(join(temp));
7925 }
7810 } 7926 }
7811 7927
7812 void transformLabel(Label_t* label, str_list& out) { 7928 void transformLabel(Label_t* label, str_list& out) {
7813 if (getLuaTarget(label) < 502) { 7929 if (getLuaTarget(label) < 502) {
7814 throw std::logic_error(_info.errorMessage("label statement is not available when not targeting Lua version 5.2 or higher"sv, label)); 7930 throw std::logic_error(_info.errorMessage("label statement is not available when not targeting Lua version 5.2 or higher"sv, label));
7815 } 7931 }
7816 out.push_back(indent() + "::"s + _parser.toString(label->label) + "::"s + nll(label)); 7932 auto labelStr = _parser.toString(label->label);
7933 int currentScope = _gotoScopes.top();
7934 if (static_cast<int>(_labels.size()) <= currentScope) {
7935 _labels.resize(currentScope + 1, std::nullopt);
7936 _labels[currentScope] = std::unordered_map<std::string, LabelNode>();
7937 }
7938 if (!_labels[currentScope]) {
7939 _labels[currentScope] = std::unordered_map<std::string, LabelNode>();
7940 }
7941 auto& scope = _labels[currentScope].value();
7942 if (auto it = scope.find(labelStr); it != scope.end()) {
7943 throw std::logic_error(_info.errorMessage("label '"s + labelStr + "' already defined at line "s + std::to_string(it->second.line), label));
7944 }
7945 scope[labelStr] = {label->m_begin.m_line, static_cast<int>(_scopes.size())};
7946 out.push_back(indent() + "::"s + labelStr + "::"s + nll(label));
7817 } 7947 }
7818 7948
7819 void transformGoto(Goto_t* gotoNode, str_list& out) { 7949 void transformGoto(Goto_t* gotoNode, str_list& out) {
7820 if (getLuaTarget(gotoNode) < 502) { 7950 if (getLuaTarget(gotoNode) < 502) {
7821 throw std::logic_error(_info.errorMessage("goto statement is not available when not targeting Lua version 5.2 or higher"sv, gotoNode)); 7951 throw std::logic_error(_info.errorMessage("goto statement is not available when not targeting Lua version 5.2 or higher"sv, gotoNode));
7822 } 7952 }
7823 out.push_back(indent() + "goto "s + _parser.toString(gotoNode->label) + nll(gotoNode)); 7953 auto labelStr = _parser.toString(gotoNode->label);
7954 gotos.push_back({gotoNode, labelStr, _gotoScopes.top(), static_cast<int>(_scopes.size())});
7955 out.push_back(indent() + "goto "s + labelStr + nll(gotoNode));
7824 } 7956 }
7825 7957
7826 void transformShortTabAppending(ShortTabAppending_t* tab, str_list& out) { 7958 void transformShortTabAppending(ShortTabAppending_t* tab, str_list& out) {