diff options
Diffstat (limited to '')
| -rw-r--r-- | makefile | 2 | ||||
| -rw-r--r-- | spec/inputs/goto.yue | 4 | ||||
| -rw-r--r-- | spec/inputs/loops.yue | 8 | ||||
| -rw-r--r-- | spec/inputs/test/loops_spec.yue | 6 | ||||
| -rw-r--r-- | spec/outputs/5.1/loops.lua | 381 | ||||
| -rw-r--r-- | spec/outputs/5.1/test/loops_spec.lua | 69 | ||||
| -rw-r--r-- | spec/outputs/goto.lua | 4 | ||||
| -rw-r--r-- | spec/outputs/loops.lua | 204 | ||||
| -rw-r--r-- | spec/outputs/test/loops_spec.lua | 51 | ||||
| -rw-r--r-- | src/3rdParty/lua/lauxlib.c | 8 | ||||
| -rw-r--r-- | src/3rdParty/lua/lobject.c | 2 | ||||
| -rw-r--r-- | src/3rdParty/lua/loslib.c | 4 | ||||
| -rw-r--r-- | src/3rdParty/lua/ltablib.c | 2 | ||||
| -rw-r--r-- | src/3rdParty/lua/luaconf.h | 5 | ||||
| -rw-r--r-- | src/3rdParty/lua/lutf8lib.c | 27 | ||||
| -rw-r--r-- | src/3rdParty/lua/lvm.c | 4 | ||||
| -rw-r--r-- | src/3rdParty/lua/lvm.h | 5 | ||||
| -rwxr-xr-x | src/yuescript/yue_ast.h | 1 | ||||
| -rw-r--r--[-rwxr-xr-x] | src/yuescript/yue_compiler.cpp | 348 |
19 files changed, 811 insertions, 324 deletions
| @@ -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 | ||
| 16 | do | 16 | do |
| 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 | ||
| 112 | x = 0 | 112 | x = 0 |
| 113 | repeat | 113 | repeat |
| 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 |
| 118 | until y == 10 | 118 | until y == 10 |
| 119 | 119 | ||
| 120 | a = 3 | 120 | a = 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 @@ | |||
| 1 | for x = 1, 10 do | ||
| 2 | print("yeah") | ||
| 3 | end | ||
| 4 | for x = 1, #something do | ||
| 5 | print("yeah") | ||
| 6 | end | ||
| 7 | for y = 100, 60, -3 do | ||
| 8 | print("count down", y) | ||
| 9 | end | ||
| 10 | for a = 1, 10 do | ||
| 11 | print("okay") | ||
| 12 | end | ||
| 13 | for a = 1, 10 do | ||
| 14 | for b = 2, 43 do | ||
| 15 | print(a, b) | ||
| 16 | end | ||
| 17 | end | ||
| 18 | for i in iter do | ||
| 19 | for j in yeah do | ||
| 20 | local x = 343 + i + j | ||
| 21 | print(i, j) | ||
| 22 | end | ||
| 23 | end | ||
| 24 | local _list_0 = something | ||
| 25 | for _index_0 = 1, #_list_0 do | ||
| 26 | local x = _list_0[_index_0] | ||
| 27 | print(x) | ||
| 28 | end | ||
| 29 | for k, v in pairs(hello) do | ||
| 30 | print(k, v) | ||
| 31 | end | ||
| 32 | for x in y, z do | ||
| 33 | print(x) | ||
| 34 | end | ||
| 35 | for x in y, z, k do | ||
| 36 | print(x) | ||
| 37 | end | ||
| 38 | local _list_1 = modules | ||
| 39 | for _index_0 = 1, #_list_1 do | ||
| 40 | local name, members = _list_1[_index_0] | ||
| 41 | print(name, member) | ||
| 42 | end | ||
| 43 | local x | ||
| 44 | x = function() | ||
| 45 | for x in y do | ||
| 46 | local _ = y | ||
| 47 | end | ||
| 48 | end | ||
| 49 | local hello = { | ||
| 50 | 1, | ||
| 51 | 2, | ||
| 52 | 3, | ||
| 53 | 4, | ||
| 54 | 5 | ||
| 55 | } | ||
| 56 | do | ||
| 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 | ||
| 67 | end | ||
| 68 | x = function() | ||
| 69 | for _index_0 = 1, #hello do | ||
| 70 | local x = hello[_index_0] | ||
| 71 | local _ = y | ||
| 72 | end | ||
| 73 | end | ||
| 74 | local t | ||
| 75 | do | ||
| 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 | ||
| 83 | end | ||
| 84 | local hmm = 0 | ||
| 85 | local y | ||
| 86 | do | ||
| 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 | ||
| 95 | end | ||
| 96 | local _ | ||
| 97 | _ = function() | ||
| 98 | for k = 10, 40 do | ||
| 99 | _ = "okay" | ||
| 100 | end | ||
| 101 | end | ||
| 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 | ||
| 110 | end | ||
| 111 | while true do | ||
| 112 | print("name") | ||
| 113 | end | ||
| 114 | while 5 + 5 do | ||
| 115 | print("okay world") | ||
| 116 | working(man) | ||
| 117 | end | ||
| 118 | while also do | ||
| 119 | i(work(too)) | ||
| 120 | _ = "okay" | ||
| 121 | end | ||
| 122 | local i = 0 | ||
| 123 | do | ||
| 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 | ||
| 131 | end | ||
| 132 | do | ||
| 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 | ||
| 142 | end | ||
| 143 | do | ||
| 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 | ||
| 151 | end | ||
| 152 | while 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 | ||
| 169 | end | ||
| 170 | for 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 | ||
| 187 | end | ||
| 188 | local a = 1 | ||
| 189 | repeat | ||
| 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 | ||
| 209 | until _cond_0 | ||
| 210 | x = 0 | ||
| 211 | repeat | ||
| 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 | ||
| 229 | until _cond_0 | ||
| 230 | a = 3 | ||
| 231 | while not (a == 0) do | ||
| 232 | a = a - 1 | ||
| 233 | end | ||
| 234 | local done = false | ||
| 235 | while not done do | ||
| 236 | done = true | ||
| 237 | end | ||
| 238 | repeat | ||
| 239 | print("hello") | ||
| 240 | until true | ||
| 241 | while not done do | ||
| 242 | x = 10 | ||
| 243 | repeat | ||
| 244 | x = x - 1 | ||
| 245 | until x == 0 | ||
| 246 | end | ||
| 247 | while not cond do | ||
| 248 | print("okay") | ||
| 249 | end | ||
| 250 | for 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 | ||
| 263 | end | ||
| 264 | local list | ||
| 265 | do | ||
| 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 | ||
| 284 | end | ||
| 285 | local _list_2 = { | ||
| 286 | 1, | ||
| 287 | 2, | ||
| 288 | 3, | ||
| 289 | 4, | ||
| 290 | 5, | ||
| 291 | 6 | ||
| 292 | } | ||
| 293 | for _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 | ||
| 311 | end | ||
| 312 | for 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 | ||
| 337 | end | ||
| 338 | while 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 | ||
| 353 | end | ||
| 354 | while 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 | ||
| 369 | end | ||
| 370 | do | ||
| 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 | ||
| 381 | end | ||
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 @@ | |||
| 1 | return 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) | ||
| 69 | end) | ||
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:: |
| 23 | end | 23 | end |
| 24 | do | 24 | do |
| 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 |
| 151 | end | 151 | end |
| 152 | while true do | 152 | while 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:: | ||
| 169 | end | 162 | end |
| 170 | for i = 1, 10 do | 163 | for 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 |
| 187 | end | 171 | end |
| 188 | local a = 1 | 172 | local a = 1 |
| 189 | repeat | 173 | repeat |
| 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 |
| 209 | until _cond_0 | 181 | print(a) |
| 182 | ::_continue_2:: | ||
| 183 | until a == 10 | ||
| 210 | x = 0 | 184 | x = 0 |
| 211 | repeat | 185 | repeat |
| 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 |
| 229 | until _cond_0 | 191 | print(y) |
| 192 | ::_continue_3:: | ||
| 193 | until y == 10 | ||
| 230 | a = 3 | 194 | a = 3 |
| 231 | while not (a == 0) do | 195 | while 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") |
| 249 | end | 213 | end |
| 250 | for x = 1, 10 do | 214 | for 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:: | ||
| 263 | end | 220 | end |
| 264 | local list | 221 | local list |
| 265 | do | 222 | do |
| 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 |
| 284 | end | 234 | end |
| @@ -292,78 +242,42 @@ local _list_2 = { | |||
| 292 | } | 242 | } |
| 293 | for _index_0 = 1, #_list_2 do | 243 | for _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:: | ||
| 311 | end | 253 | end |
| 312 | for x = 1, 10 do | 254 | for 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:: | ||
| 337 | end | 265 | end |
| 338 | while true do | 266 | while 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:: | ||
| 353 | end | 272 | end |
| 354 | while true do | 273 | while 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:: | ||
| 367 | end | 281 | end |
| 368 | do | 282 | do |
| 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) |
| 69 | end) | 52 | end) |
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 | */ |
| 532 | static size_t newbuffsize (luaL_Buffer *B, size_t sz) { | 532 | static 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 | ||
| 254 | static int iter_codes (lua_State *L) { | 258 | static 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 | |||
| 774 | lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { | 772 | lua_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 | ||
| 115 | LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); | 120 | LUAI_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 | ||
| 60 | typedef std::list<std::string> str_list; | 61 | typedef std::list<std::string> str_list; |
| 61 | 62 | ||
| 62 | const std::string_view version = "0.15.3"sv; | 63 | const std::string_view version = "0.15.4"sv; |
| 63 | const std::string_view extension = "yue"sv; | 64 | const std::string_view extension = "yue"sv; |
| 64 | 65 | ||
| 65 | class YueCompilerImpl { | 66 | class 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) { |
