aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2024-10-19 00:35:11 +0800
committerLi Jin <dragon-fly@qq.com>2024-10-19 00:35:11 +0800
commit1334c0ae67fdf4cb1377e0e7a3ef291f5cf694c0 (patch)
tree8bd3fbeb396fd2fce6e5b34c3ee10f4923feca72
parent05da3cbfa3689e6c229c41156d0dd08ab554cd77 (diff)
downloadyuescript-1334c0ae67fdf4cb1377e0e7a3ef291f5cf694c0.tar.gz
yuescript-1334c0ae67fdf4cb1377e0e7a3ef291f5cf694c0.tar.bz2
yuescript-1334c0ae67fdf4cb1377e0e7a3ef291f5cf694c0.zip
Fixed issue #174.
-rwxr-xr-xdoc/docs/doc/README.md16
-rwxr-xr-xdoc/docs/zh/doc/README.md90
-rw-r--r--spec/inputs/loops.yue17
-rw-r--r--spec/outputs/5.1/loops.lua49
-rw-r--r--spec/outputs/codes_from_doc.lua16
-rw-r--r--spec/outputs/codes_from_doc_zh.lua16
-rw-r--r--spec/outputs/loops.lua37
-rw-r--r--src/3rdParty/lua/lauxlib.c28
-rw-r--r--src/3rdParty/lua/lcode.c6
-rw-r--r--src/3rdParty/lua/ldebug.c41
-rw-r--r--src/3rdParty/lua/ldo.c4
-rw-r--r--src/3rdParty/lua/lgc.c2
-rw-r--r--src/3rdParty/lua/liolib.c27
-rw-r--r--src/3rdParty/lua/lmathlib.c2
-rw-r--r--src/3rdParty/lua/loslib.c2
-rw-r--r--src/3rdParty/lua/lstring.c2
-rw-r--r--src/3rdParty/lua/lua.h34
-rw-r--r--src/3rdParty/lua/luaconf.h2
-rw-r--r--src/3rdParty/lua/lundump.h2
-rw-r--r--src/3rdParty/lua/lvm.c4
-rw-r--r--src/yuescript/yue_ast.cpp2
-rw-r--r--src/yuescript/yue_ast.h3
-rw-r--r--src/yuescript/yue_compiler.cpp37
-rw-r--r--src/yuescript/yue_parser.cpp2
24 files changed, 332 insertions, 109 deletions
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md
index f6aebfc..83d351f 100755
--- a/doc/docs/doc/README.md
+++ b/doc/docs/doc/README.md
@@ -1313,6 +1313,22 @@ print "OK"
1313</pre> 1313</pre>
1314</YueDisplay> 1314</YueDisplay>
1315 1315
1316### While Assignment
1317
1318You can also use if assignment in a while loop to get the value as the loop condition.
1319```moonscript
1320while byte := stream\read_one!
1321 -- do something with the byte
1322 print byte
1323```
1324<YueDisplay>
1325<pre>
1326while byte := stream\read_one!
1327 -- do something with the byte
1328 print byte
1329</pre>
1330</YueDisplay>
1331
1316## Varargs Assignment 1332## Varargs Assignment
1317 1333
1318You can assign the results returned from a function to a varargs symbol `...`. And then access its content using the Lua way. 1334You can assign the results returned from a function to a varargs symbol `...`. And then access its content using the Lua way.
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md
index 871edd2..bc53075 100755
--- a/doc/docs/zh/doc/README.md
+++ b/doc/docs/zh/doc/README.md
@@ -1310,6 +1310,22 @@ print "好的"
1310</pre> 1310</pre>
1311</YueDisplay> 1311</YueDisplay>
1312 1312
1313### While 赋值
1314
1315您可以在 while 循环中同样使用赋值来获取循环条件的值。
1316```moonscript
1317while byte := stream\read_one!
1318 -- 对 byte 做一些操作
1319 print byte
1320```
1321<YueDisplay>
1322<pre>
1323while byte := stream\read_one!
1324 -- 对 byte 做一些操作
1325 print byte
1326</pre>
1327</YueDisplay>
1328
1313## 可变参数赋值 1329## 可变参数赋值
1314 1330
1315您可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用Lua的方式访问其内容。 1331您可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用Lua的方式访问其内容。
@@ -3550,7 +3566,7 @@ print i, k -- 这些已经被更新
3550月之脚本版本。 3566月之脚本版本。
3551 3567
3552**签名:** 3568**签名:**
3553```tl 3569```lua
3554version: string 3570version: string
3555``` 3571```
3556 3572
@@ -3563,7 +3579,7 @@ version: string
3563当前平台的文件分隔符。 3579当前平台的文件分隔符。
3564 3580
3565**签名:** 3581**签名:**
3566```tl 3582```lua
3567dirsep: string 3583dirsep: string
3568``` 3584```
3569 3585
@@ -3576,7 +3592,7 @@ dirsep: string
3576编译模块代码缓存。 3592编译模块代码缓存。
3577 3593
3578**签名:** 3594**签名:**
3579```tl 3595```lua
3580yue_compiled: {string: string} 3596yue_compiled: {string: string}
3581``` 3597```
3582 3598
@@ -3589,7 +3605,7 @@ yue_compiled: {string: string}
3589月之脚本的编译函数。它将 Yuescript 代码编译为 Lua 代码。 3605月之脚本的编译函数。它将 Yuescript 代码编译为 Lua 代码。
3590 3606
3591**签名:** 3607**签名:**
3592```tl 3608```lua
3593to_lua: function(code: string, config?: Config): 3609to_lua: function(code: string, config?: Config):
3594 --[[codes]] string | nil, 3610 --[[codes]] string | nil,
3595 --[[error]] string | nil, 3611 --[[error]] string | nil,
@@ -3620,7 +3636,7 @@ to_lua: function(code: string, config?: Config):
3620检查源文件是否存在的函数。可以覆盖该函数以自定义行为。 3636检查源文件是否存在的函数。可以覆盖该函数以自定义行为。
3621 3637
3622**签名:** 3638**签名:**
3623```tl 3639```lua
3624file_exist: function(filename: string): boolean 3640file_exist: function(filename: string): boolean
3625``` 3641```
3626 3642
@@ -3645,7 +3661,7 @@ file_exist: function(filename: string): boolean
3645读取源文件的函数。可以覆盖该函数以自定义行为。 3661读取源文件的函数。可以覆盖该函数以自定义行为。
3646 3662
3647**签名:** 3663**签名:**
3648```tl 3664```lua
3649read_file: function(filename: string): string 3665read_file: function(filename: string): string
3650``` 3666```
3651 3667
@@ -3670,7 +3686,7 @@ read_file: function(filename: string): string
3670将 Yuescript 加载器插入到 Lua 包加载器(搜索器)中。 3686将 Yuescript 加载器插入到 Lua 包加载器(搜索器)中。
3671 3687
3672**签名:** 3688**签名:**
3673```tl 3689```lua
3674insert_loader: function(pos?: integer): boolean 3690insert_loader: function(pos?: integer): boolean
3675``` 3691```
3676 3692
@@ -3695,7 +3711,7 @@ insert_loader: function(pos?: integer): boolean
3695从 Lua 包加载器(搜索器)中移除 Yuescript 加载器。 3711从 Lua 包加载器(搜索器)中移除 Yuescript 加载器。
3696 3712
3697**签名:** 3713**签名:**
3698```tl 3714```lua
3699remove_loader: function(): boolean 3715remove_loader: function(): boolean
3700``` 3716```
3701 3717
@@ -3714,7 +3730,7 @@ remove_loader: function(): boolean
3714将 Yuescript 代码字符串加载为一个函数。 3730将 Yuescript 代码字符串加载为一个函数。
3715 3731
3716**签名:** 3732**签名:**
3717```tl 3733```lua
3718loadstring: function(input: string, chunkname: string, env: table, config?: Config): 3734loadstring: function(input: string, chunkname: string, env: table, config?: Config):
3719 --[[loaded function]] nil | function(...: any): (any...), 3735 --[[loaded function]] nil | function(...: any): (any...),
3720 --[[error]] string | nil 3736 --[[error]] string | nil
@@ -3745,7 +3761,7 @@ loadstring: function(input: string, chunkname: string, env: table, config?: Conf
3745将 Yuescript 代码字符串加载为一个函数。 3761将 Yuescript 代码字符串加载为一个函数。
3746 3762
3747**签名:** 3763**签名:**
3748```tl 3764```lua
3749loadstring: function(input: string, chunkname: string, config?: Config): 3765loadstring: function(input: string, chunkname: string, config?: Config):
3750 --[[loaded function]] nil | function(...: any): (any...), 3766 --[[loaded function]] nil | function(...: any): (any...),
3751 --[[error]] string | nil 3767 --[[error]] string | nil
@@ -3775,7 +3791,7 @@ loadstring: function(input: string, chunkname: string, config?: Config):
3775将 Yuescript 代码字符串加载为一个函数。 3791将 Yuescript 代码字符串加载为一个函数。
3776 3792
3777**签名:** 3793**签名:**
3778```tl 3794```lua
3779loadstring: function(input: string, config?: Config): 3795loadstring: function(input: string, config?: Config):
3780 --[[loaded function]] nil | function(...: any): (any...), 3796 --[[loaded function]] nil | function(...: any): (any...),
3781 --[[error]] string | nil 3797 --[[error]] string | nil
@@ -3804,7 +3820,7 @@ loadstring: function(input: string, config?: Config):
3804将 Yuescript 代码文件加载为一个函数。 3820将 Yuescript 代码文件加载为一个函数。
3805 3821
3806**签名:** 3822**签名:**
3807```tl 3823```lua
3808loadfile: function(filename: string, env: table, config?: Config): 3824loadfile: function(filename: string, env: table, config?: Config):
3809 nil | function(...: any): (any...), 3825 nil | function(...: any): (any...),
3810 string | nil 3826 string | nil
@@ -3834,7 +3850,7 @@ loadfile: function(filename: string, env: table, config?: Config):
3834将 Yuescript 代码文件加载为一个函数。 3850将 Yuescript 代码文件加载为一个函数。
3835 3851
3836**签名:** 3852**签名:**
3837```tl 3853```lua
3838loadfile: function(filename: string, config?: Config): 3854loadfile: function(filename: string, config?: Config):
3839 nil | function(...: any): (any...), 3855 nil | function(...: any): (any...),
3840 string | nil 3856 string | nil
@@ -3863,7 +3879,7 @@ loadfile: function(filename: string, config?: Config):
3863将 Yuescript 代码文件加载为一个函数并执行。 3879将 Yuescript 代码文件加载为一个函数并执行。
3864 3880
3865**签名:** 3881**签名:**
3866```tl 3882```lua
3867dofile: function(filename: string, env: table, config?: Config): any... 3883dofile: function(filename: string, env: table, config?: Config): any...
3868``` 3884```
3869 3885
@@ -3890,7 +3906,7 @@ dofile: function(filename: string, env: table, config?: Config): any...
3890将 Yuescript 代码文件加载为一个函数并执行。 3906将 Yuescript 代码文件加载为一个函数并执行。
3891 3907
3892**签名:** 3908**签名:**
3893```tl 3909```lua
3894dofile: function(filename: string, config?: Config): any... 3910dofile: function(filename: string, config?: Config): any...
3895``` 3911```
3896 3912
@@ -3916,7 +3932,7 @@ dofile: function(filename: string, config?: Config): any...
3916将 Yuescript 模块名解析为文件路径。 3932将 Yuescript 模块名解析为文件路径。
3917 3933
3918**签名:** 3934**签名:**
3919```tl 3935```lua
3920find_modulepath: function(name: string): string 3936find_modulepath: function(name: string): string
3921``` 3937```
3922 3938
@@ -3943,7 +3959,7 @@ find_modulepath: function(name: string): string
3943当发生错误时,将错误信息中的代码行号重写为 Yuescript 代码中的原始行号。 3959当发生错误时,将错误信息中的代码行号重写为 Yuescript 代码中的原始行号。
3944 3960
3945**签名:** 3961**签名:**
3946```tl 3962```lua
3947pcall: function(f: function, ...: any): boolean, any... 3963pcall: function(f: function, ...: any): boolean, any...
3948``` 3964```
3949 3965
@@ -3970,7 +3986,7 @@ pcall: function(f: function, ...: any): boolean, any...
3970如果模块是 Yuescript 模块且加载失败,则将错误信息中的代码行号重写为 Yuescript 代码中的原始行号。 3986如果模块是 Yuescript 模块且加载失败,则将错误信息中的代码行号重写为 Yuescript 代码中的原始行号。
3971 3987
3972**签名:** 3988**签名:**
3973```tl 3989```lua
3974require: function(name: string): any... 3990require: function(name: string): any...
3975``` 3991```
3976 3992
@@ -3995,7 +4011,7 @@ require: function(name: string): any...
3995检查传递的值的内部结构,并打印值出它的字符串表示。 4011检查传递的值的内部结构,并打印值出它的字符串表示。
3996 4012
3997**签名:** 4013**签名:**
3998```tl 4014```lua
3999p: function(...: any) 4015p: function(...: any)
4000``` 4016```
4001 4017
@@ -4014,7 +4030,7 @@ p: function(...: any)
4014当前编译器选项。 4030当前编译器选项。
4015 4031
4016**签名:** 4032**签名:**
4017```tl 4033```lua
4018options: Config.Options 4034options: Config.Options
4019``` 4035```
4020 4036
@@ -4027,7 +4043,7 @@ options: Config.Options
4027重写堆栈跟踪中的行号为 Yuescript 代码中的原始行号的 traceback 函数。 4043重写堆栈跟踪中的行号为 Yuescript 代码中的原始行号的 traceback 函数。
4028 4044
4029**签名:** 4045**签名:**
4030```tl 4046```lua
4031traceback: function(message: string): string 4047traceback: function(message: string): string
4032``` 4048```
4033 4049
@@ -4052,7 +4068,7 @@ traceback: function(message: string): string
4052检查代码是否匹配指定的 AST。 4068检查代码是否匹配指定的 AST。
4053 4069
4054**签名:** 4070**签名:**
4055```tl 4071```lua
4056is_ast: function(astName: string, code: string): boolean 4072is_ast: function(astName: string, code: string): boolean
4057``` 4073```
4058 4074
@@ -4078,7 +4094,7 @@ is_ast: function(astName: string, code: string): boolean
4078AST 类型定义,带有名称、行、列和子节点。 4094AST 类型定义,带有名称、行、列和子节点。
4079 4095
4080**签名:** 4096**签名:**
4081```tl 4097```lua
4082type AST = {string, integer, integer, any} 4098type AST = {string, integer, integer, any}
4083``` 4099```
4084 4100
@@ -4091,7 +4107,7 @@ type AST = {string, integer, integer, any}
4091将代码转换为 AST。 4107将代码转换为 AST。
4092 4108
4093**签名:** 4109**签名:**
4094```tl 4110```lua
4095to_ast: function(code: string, flattenLevel?: number, astName?: string): 4111to_ast: function(code: string, flattenLevel?: number, astName?: string):
4096 --[[AST]] AST | nil, 4112 --[[AST]] AST | nil,
4097 --[[error]] nil | string 4113 --[[error]] nil | string
@@ -4114,7 +4130,7 @@ to_ast: function(code: string, flattenLevel?: number, astName?: string):
4114如果发生加载失败,则将错误信息中的代码行号重写为 Yuescript 代码中的原始行号。 4130如果发生加载失败,则将错误信息中的代码行号重写为 Yuescript 代码中的原始行号。
4115 4131
4116**签名:** 4132**签名:**
4117```tl 4133```lua
4118metamethod __call: function(self: yue, module: string): any... 4134metamethod __call: function(self: yue, module: string): any...
4119``` 4135```
4120 4136
@@ -4145,7 +4161,7 @@ metamethod __call: function(self: yue, module: string): any...
4145编译器是否应该收集代码中出现的全局变量。 4161编译器是否应该收集代码中出现的全局变量。
4146 4162
4147**签名:** 4163**签名:**
4148```tl 4164```lua
4149lint_global: boolean 4165lint_global: boolean
4150``` 4166```
4151 4167
@@ -4158,7 +4174,7 @@ lint_global: boolean
4158编译器是否应该对根层级的代码块进行隐式的表达式返回。 4174编译器是否应该对根层级的代码块进行隐式的表达式返回。
4159 4175
4160**签名:** 4176**签名:**
4161```tl 4177```lua
4162implicit_return_root: boolean 4178implicit_return_root: boolean
4163``` 4179```
4164 4180
@@ -4171,7 +4187,7 @@ implicit_return_root: boolean
4171编译器是否应该在编译后的代码中保留原始行号。 4187编译器是否应该在编译后的代码中保留原始行号。
4172 4188
4173**签名:** 4189**签名:**
4174```tl 4190```lua
4175reserve_line_number: boolean 4191reserve_line_number: boolean
4176``` 4192```
4177 4193
@@ -4184,7 +4200,7 @@ reserve_line_number: boolean
4184编译器是否应该在编译后的代码中使用空格字符而不是制表符字符。 4200编译器是否应该在编译后的代码中使用空格字符而不是制表符字符。
4185 4201
4186**签名:** 4202**签名:**
4187```tl 4203```lua
4188space_over_tab: boolean 4204space_over_tab: boolean
4189``` 4205```
4190 4206
@@ -4197,7 +4213,7 @@ space_over_tab: boolean
4197编译器是否应该将要编译的代码视为当前正在编译的模块。仅供编译器内部使用。 4213编译器是否应该将要编译的代码视为当前正在编译的模块。仅供编译器内部使用。
4198 4214
4199**签名:** 4215**签名:**
4200```tl 4216```lua
4201same_module: boolean 4217same_module: boolean
4202``` 4218```
4203 4219
@@ -4210,7 +4226,7 @@ same_module: boolean
4210编译器错误消息是否应该包含行号偏移量。仅供编译器内部使用。 4226编译器错误消息是否应该包含行号偏移量。仅供编译器内部使用。
4211 4227
4212**签名:** 4228**签名:**
4213```tl 4229```lua
4214line_offset: integer 4230line_offset: integer
4215``` 4231```
4216 4232
@@ -4223,7 +4239,7 @@ line_offset: integer
4223目标 Lua 版本枚举。 4239目标 Lua 版本枚举。
4224 4240
4225**签名:** 4241**签名:**
4226```tl 4242```lua
4227enum LuaTarget 4243enum LuaTarget
4228 "5.1" 4244 "5.1"
4229 "5.2" 4245 "5.2"
@@ -4242,7 +4258,7 @@ end
4242要传递给编译函数的额外选项。 4258要传递给编译函数的额外选项。
4243 4259
4244**签名:** 4260**签名:**
4245```tl 4261```lua
4246options: Options 4262options: Options
4247``` 4263```
4248 4264
@@ -4261,7 +4277,7 @@ options: Options
4261编译目标 Lua 版本。 4277编译目标 Lua 版本。
4262 4278
4263**签名:** 4279**签名:**
4264```tl 4280```lua
4265target: LuaTarget 4281target: LuaTarget
4266``` 4282```
4267 4283
@@ -4274,7 +4290,7 @@ target: LuaTarget
4274额外模块搜索路径。 4290额外模块搜索路径。
4275 4291
4276**签名:** 4292**签名:**
4277```tl 4293```lua
4278path: string 4294path: string
4279``` 4295```
4280 4296
@@ -4287,7 +4303,7 @@ path: string
4287是否在回溯错误消息中输出代码块的局部变量。默认为 false。 4303是否在回溯错误消息中输出代码块的局部变量。默认为 false。
4288 4304
4289**签名:** 4305**签名:**
4290```tl 4306```lua
4291dump_locals: boolean 4307dump_locals: boolean
4292``` 4308```
4293 4309
@@ -4300,7 +4316,7 @@ dump_locals: boolean
4300是否简化输出的错误消息。默认为 true。 4316是否简化输出的错误消息。默认为 true。
4301 4317
4302**签名:** 4318**签名:**
4303```tl 4319```lua
4304simplified: boolean 4320simplified: boolean
4305``` 4321```
4306 4322
diff --git a/spec/inputs/loops.yue b/spec/inputs/loops.yue
index 5cadbf0..c5b28b3 100644
--- a/spec/inputs/loops.yue
+++ b/spec/inputs/loops.yue
@@ -196,3 +196,20 @@ do
196 print i 196 print i
197 continue 197 continue
198 print "abc" 198 print "abc"
199
200do
201 while byte := stream::read_one!
202 -- do something with the byte
203 continue if byte == 0
204 print byte
205
206do
207 local func
208 while success, result := try func 1, 2, 3
209 catch err
210 print err
211 print result
212
213do
214 until x := func 'a', b do
215 print "false expected"
diff --git a/spec/outputs/5.1/loops.lua b/spec/outputs/5.1/loops.lua
index cc019e0..57b19be 100644
--- a/spec/outputs/5.1/loops.lua
+++ b/spec/outputs/5.1/loops.lua
@@ -440,3 +440,52 @@ do
440 end 440 end
441 end 441 end
442end 442end
443do
444 repeat
445 local _cond_0 = false
446 local _continue_0 = false
447 repeat
448 local byte = stream:read_one()
449 if byte then
450 if byte == 0 then
451 _cond_0 = false
452 _continue_0 = true
453 break
454 end
455 print(byte)
456 else
457 break
458 end
459 _cond_0 = false
460 _continue_0 = true
461 until true
462 if not _continue_0 then
463 break
464 end
465 until _cond_0
466end
467do
468 local func
469 repeat
470 local success, result = xpcall(function()
471 return func(1, 2, 3)
472 end, function(err)
473 return print(err)
474 end)
475 if success then
476 print(result)
477 else
478 break
479 end
480 until false
481end
482do
483 repeat
484 x = func('a', b)
485 if not x then
486 print("false expected")
487 else
488 break
489 end
490 until false
491end
diff --git a/spec/outputs/codes_from_doc.lua b/spec/outputs/codes_from_doc.lua
index 4073056..e2bba8e 100644
--- a/spec/outputs/codes_from_doc.lua
+++ b/spec/outputs/codes_from_doc.lua
@@ -585,6 +585,14 @@ do
585 end 585 end
586end 586end
587print("OK") 587print("OK")
588repeat
589 local byte = stream:read_one()
590 if byte then
591 print(byte)
592 else
593 break
594 end
595until false
588local list = { 596local list = {
589 1, 597 1,
590 2, 598 2,
@@ -2583,6 +2591,14 @@ do
2583 end 2591 end
2584end 2592end
2585print("OK") 2593print("OK")
2594repeat
2595 local byte = stream:read_one()
2596 if byte then
2597 print(byte)
2598 else
2599 break
2600 end
2601until false
2586local list = { 2602local list = {
2587 1, 2603 1,
2588 2, 2604 2,
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua
index f251450..4839525 100644
--- a/spec/outputs/codes_from_doc_zh.lua
+++ b/spec/outputs/codes_from_doc_zh.lua
@@ -585,6 +585,14 @@ do
585 end 585 end
586end 586end
587print("好的") 587print("好的")
588repeat
589 local byte = stream:read_one()
590 if byte then
591 print(byte)
592 else
593 break
594 end
595until false
588local list = { 596local list = {
589 1, 597 1,
590 2, 598 2,
@@ -2577,6 +2585,14 @@ do
2577 end 2585 end
2578end 2586end
2579print("好的") 2587print("好的")
2588repeat
2589 local byte = stream:read_one()
2590 if byte then
2591 print(byte)
2592 else
2593 break
2594 end
2595until false
2580local list = { 2596local list = {
2581 1, 2597 1,
2582 2, 2598 2,
diff --git a/spec/outputs/loops.lua b/spec/outputs/loops.lua
index 40e27b9..8624d49 100644
--- a/spec/outputs/loops.lua
+++ b/spec/outputs/loops.lua
@@ -333,3 +333,40 @@ do
333 ::_continue_11:: 333 ::_continue_11::
334 end 334 end
335end 335end
336do
337 repeat
338 local byte = stream:read_one()
339 if byte then
340 if byte == 0 then
341 goto _continue_13
342 end
343 print(byte)
344 else
345 break
346 end
347 ::_continue_13::
348 until false
349end
350do
351 local func
352 repeat
353 local success, result = xpcall(func, function(err)
354 return print(err)
355 end, 1, 2, 3)
356 if success then
357 print(result)
358 else
359 break
360 end
361 until false
362end
363do
364 repeat
365 x = func('a', b)
366 if not x then
367 print("false expected")
368 else
369 break
370 end
371 until false
372end
diff --git a/src/3rdParty/lua/lauxlib.c b/src/3rdParty/lua/lauxlib.c
index 4ca6c65..923105e 100644
--- a/src/3rdParty/lua/lauxlib.c
+++ b/src/3rdParty/lua/lauxlib.c
@@ -80,6 +80,7 @@ static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
80 int top = lua_gettop(L); 80 int top = lua_gettop(L);
81 lua_getinfo(L, "f", ar); /* push function */ 81 lua_getinfo(L, "f", ar); /* push function */
82 lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); 82 lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
83 luaL_checkstack(L, 6, "not enough stack"); /* slots for 'findfield' */
83 if (findfield(L, top + 1, 2)) { 84 if (findfield(L, top + 1, 2)) {
84 const char *name = lua_tostring(L, -1); 85 const char *name = lua_tostring(L, -1);
85 if (strncmp(name, LUA_GNAME ".", 3) == 0) { /* name start with '_G.'? */ 86 if (strncmp(name, LUA_GNAME ".", 3) == 0) { /* name start with '_G.'? */
@@ -249,11 +250,13 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
249 return 1; 250 return 1;
250 } 251 }
251 else { 252 else {
253 const char *msg;
252 luaL_pushfail(L); 254 luaL_pushfail(L);
255 msg = (en != 0) ? strerror(en) : "(no extra info)";
253 if (fname) 256 if (fname)
254 lua_pushfstring(L, "%s: %s", fname, strerror(en)); 257 lua_pushfstring(L, "%s: %s", fname, msg);
255 else 258 else
256 lua_pushstring(L, strerror(en)); 259 lua_pushstring(L, msg);
257 lua_pushinteger(L, en); 260 lua_pushinteger(L, en);
258 return 3; 261 return 3;
259 } 262 }
@@ -732,9 +735,12 @@ static const char *getF (lua_State *L, void *ud, size_t *size) {
732 735
733 736
734static int errfile (lua_State *L, const char *what, int fnameindex) { 737static int errfile (lua_State *L, const char *what, int fnameindex) {
735 const char *serr = strerror(errno); 738 int err = errno;
736 const char *filename = lua_tostring(L, fnameindex) + 1; 739 const char *filename = lua_tostring(L, fnameindex) + 1;
737 lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); 740 if (err != 0)
741 lua_pushfstring(L, "cannot %s %s: %s", what, filename, strerror(err));
742 else
743 lua_pushfstring(L, "cannot %s %s", what, filename);
738 lua_remove(L, fnameindex); 744 lua_remove(L, fnameindex);
739 return LUA_ERRFILE; 745 return LUA_ERRFILE;
740} 746}
@@ -787,6 +793,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
787 } 793 }
788 else { 794 else {
789 lua_pushfstring(L, "@%s", filename); 795 lua_pushfstring(L, "@%s", filename);
796 errno = 0;
790 lf.f = fopen(filename, "r"); 797 lf.f = fopen(filename, "r");
791 if (lf.f == NULL) return errfile(L, "open", fnameindex); 798 if (lf.f == NULL) return errfile(L, "open", fnameindex);
792 } 799 }
@@ -796,6 +803,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
796 if (c == LUA_SIGNATURE[0]) { /* binary file? */ 803 if (c == LUA_SIGNATURE[0]) { /* binary file? */
797 lf.n = 0; /* remove possible newline */ 804 lf.n = 0; /* remove possible newline */
798 if (filename) { /* "real" file? */ 805 if (filename) { /* "real" file? */
806 errno = 0;
799 lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ 807 lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
800 if (lf.f == NULL) return errfile(L, "reopen", fnameindex); 808 if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
801 skipcomment(lf.f, &c); /* re-read initial portion */ 809 skipcomment(lf.f, &c); /* re-read initial portion */
@@ -803,6 +811,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
803 } 811 }
804 if (c != EOF) 812 if (c != EOF)
805 lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ 813 lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */
814 errno = 0;
806 status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); 815 status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode);
807 readstatus = ferror(lf.f); 816 readstatus = ferror(lf.f);
808 if (filename) fclose(lf.f); /* close file (even in case of errors) */ 817 if (filename) fclose(lf.f); /* close file (even in case of errors) */
@@ -933,7 +942,7 @@ LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
933LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { 942LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
934 luaL_checkstack(L, nup, "too many upvalues"); 943 luaL_checkstack(L, nup, "too many upvalues");
935 for (; l->name != NULL; l++) { /* fill the table with given functions */ 944 for (; l->name != NULL; l++) { /* fill the table with given functions */
936 if (l->func == NULL) /* place holder? */ 945 if (l->func == NULL) /* placeholder? */
937 lua_pushboolean(L, 0); 946 lua_pushboolean(L, 0);
938 else { 947 else {
939 int i; 948 int i;
@@ -1025,9 +1034,14 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
1025} 1034}
1026 1035
1027 1036
1037/*
1038** Standard panic funcion just prints an error message. The test
1039** with 'lua_type' avoids possible memory errors in 'lua_tostring'.
1040*/
1028static int panic (lua_State *L) { 1041static int panic (lua_State *L) {
1029 const char *msg = lua_tostring(L, -1); 1042 const char *msg = (lua_type(L, -1) == LUA_TSTRING)
1030 if (msg == NULL) msg = "error object is not a string"; 1043 ? lua_tostring(L, -1)
1044 : "error object is not a string";
1031 lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", 1045 lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
1032 msg); 1046 msg);
1033 return 0; /* return to Lua to abort */ 1047 return 0; /* return to Lua to abort */
diff --git a/src/3rdParty/lua/lcode.c b/src/3rdParty/lua/lcode.c
index caac6ba..8761614 100644
--- a/src/3rdParty/lua/lcode.c
+++ b/src/3rdParty/lua/lcode.c
@@ -776,7 +776,8 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
776 break; 776 break;
777 } 777 }
778 case VLOCAL: { /* already in a register */ 778 case VLOCAL: { /* already in a register */
779 e->u.info = e->u.var.ridx; 779 int temp = e->u.var.ridx;
780 e->u.info = temp; /* (can't do a direct assignment; values overlap) */
780 e->k = VNONRELOC; /* becomes a non-relocatable value */ 781 e->k = VNONRELOC; /* becomes a non-relocatable value */
781 break; 782 break;
782 } 783 }
@@ -1283,8 +1284,9 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
1283 if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ 1284 if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */
1284 luaK_exp2anyreg(fs, t); /* put it in a register */ 1285 luaK_exp2anyreg(fs, t); /* put it in a register */
1285 if (t->k == VUPVAL) { 1286 if (t->k == VUPVAL) {
1287 int temp = t->u.info; /* upvalue index */
1286 lua_assert(isKstr(fs, k)); 1288 lua_assert(isKstr(fs, k));
1287 t->u.ind.t = t->u.info; /* upvalue index */ 1289 t->u.ind.t = temp; /* (can't do a direct assignment; values overlap) */
1288 t->u.ind.idx = k->u.info; /* literal short string */ 1290 t->u.ind.idx = k->u.info; /* literal short string */
1289 t->k = VINDEXUP; 1291 t->k = VINDEXUP;
1290 } 1292 }
diff --git a/src/3rdParty/lua/ldebug.c b/src/3rdParty/lua/ldebug.c
index b1f16ac..591b352 100644
--- a/src/3rdParty/lua/ldebug.c
+++ b/src/3rdParty/lua/ldebug.c
@@ -31,7 +31,7 @@
31 31
32 32
33 33
34#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL) 34#define LuaClosure(f) ((f) != NULL && (f)->c.tt == LUA_VLCL)
35 35
36 36
37static const char *funcnamefromcall (lua_State *L, CallInfo *ci, 37static const char *funcnamefromcall (lua_State *L, CallInfo *ci,
@@ -254,7 +254,7 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
254 254
255 255
256static void funcinfo (lua_Debug *ar, Closure *cl) { 256static void funcinfo (lua_Debug *ar, Closure *cl) {
257 if (noLuaClosure(cl)) { 257 if (!LuaClosure(cl)) {
258 ar->source = "=[C]"; 258 ar->source = "=[C]";
259 ar->srclen = LL("=[C]"); 259 ar->srclen = LL("=[C]");
260 ar->linedefined = -1; 260 ar->linedefined = -1;
@@ -288,29 +288,31 @@ static int nextline (const Proto *p, int currentline, int pc) {
288 288
289 289
290static void collectvalidlines (lua_State *L, Closure *f) { 290static void collectvalidlines (lua_State *L, Closure *f) {
291 if (noLuaClosure(f)) { 291 if (!LuaClosure(f)) {
292 setnilvalue(s2v(L->top.p)); 292 setnilvalue(s2v(L->top.p));
293 api_incr_top(L); 293 api_incr_top(L);
294 } 294 }
295 else { 295 else {
296 int i;
297 TValue v;
298 const Proto *p = f->l.p; 296 const Proto *p = f->l.p;
299 int currentline = p->linedefined; 297 int currentline = p->linedefined;
300 Table *t = luaH_new(L); /* new table to store active lines */ 298 Table *t = luaH_new(L); /* new table to store active lines */
301 sethvalue2s(L, L->top.p, t); /* push it on stack */ 299 sethvalue2s(L, L->top.p, t); /* push it on stack */
302 api_incr_top(L); 300 api_incr_top(L);
303 setbtvalue(&v); /* boolean 'true' to be the value of all indices */ 301 if (p->lineinfo != NULL) { /* proto with debug information? */
304 if (!p->is_vararg) /* regular function? */ 302 int i;
305 i = 0; /* consider all instructions */ 303 TValue v;
306 else { /* vararg function */ 304 setbtvalue(&v); /* boolean 'true' to be the value of all indices */
307 lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP); 305 if (!p->is_vararg) /* regular function? */
308 currentline = nextline(p, currentline, 0); 306 i = 0; /* consider all instructions */
309 i = 1; /* skip first instruction (OP_VARARGPREP) */ 307 else { /* vararg function */
310 } 308 lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP);
311 for (; i < p->sizelineinfo; i++) { /* for each instruction */ 309 currentline = nextline(p, currentline, 0);
312 currentline = nextline(p, currentline, i); /* get its line */ 310 i = 1; /* skip first instruction (OP_VARARGPREP) */
313 luaH_setint(L, t, currentline, &v); /* table[line] = true */ 311 }
312 for (; i < p->sizelineinfo; i++) { /* for each instruction */
313 currentline = nextline(p, currentline, i); /* get its line */
314 luaH_setint(L, t, currentline, &v); /* table[line] = true */
315 }
314 } 316 }
315 } 317 }
316} 318}
@@ -339,7 +341,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
339 } 341 }
340 case 'u': { 342 case 'u': {
341 ar->nups = (f == NULL) ? 0 : f->c.nupvalues; 343 ar->nups = (f == NULL) ? 0 : f->c.nupvalues;
342 if (noLuaClosure(f)) { 344 if (!LuaClosure(f)) {
343 ar->isvararg = 1; 345 ar->isvararg = 1;
344 ar->nparams = 0; 346 ar->nparams = 0;
345 } 347 }
@@ -925,12 +927,12 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) {
925 } 927 }
926 pc++; /* reference is always next instruction */ 928 pc++; /* reference is always next instruction */
927 ci->u.l.savedpc = pc; /* save 'pc' */ 929 ci->u.l.savedpc = pc; /* save 'pc' */
928 counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); 930 counthook = (mask & LUA_MASKCOUNT) && (--L->hookcount == 0);
929 if (counthook) 931 if (counthook)
930 resethookcount(L); /* reset count */ 932 resethookcount(L); /* reset count */
931 else if (!(mask & LUA_MASKLINE)) 933 else if (!(mask & LUA_MASKLINE))
932 return 1; /* no line hook and count != 0; nothing to be done now */ 934 return 1; /* no line hook and count != 0; nothing to be done now */
933 if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ 935 if (ci->callstatus & CIST_HOOKYIELD) { /* hook yielded last time? */
934 ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ 936 ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
935 return 1; /* do not call hook again (VM yielded, so it did not move) */ 937 return 1; /* do not call hook again (VM yielded, so it did not move) */
936 } 938 }
@@ -952,7 +954,6 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) {
952 if (L->status == LUA_YIELD) { /* did hook yield? */ 954 if (L->status == LUA_YIELD) { /* did hook yield? */
953 if (counthook) 955 if (counthook)
954 L->hookcount = 1; /* undo decrement to zero */ 956 L->hookcount = 1; /* undo decrement to zero */
955 ci->u.l.savedpc--; /* undo increment (resume will increment it again) */
956 ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ 957 ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
957 luaD_throw(L, LUA_YIELD); 958 luaD_throw(L, LUA_YIELD);
958 } 959 }
diff --git a/src/3rdParty/lua/ldo.c b/src/3rdParty/lua/ldo.c
index bd8d965..ea05295 100644
--- a/src/3rdParty/lua/ldo.c
+++ b/src/3rdParty/lua/ldo.c
@@ -792,6 +792,10 @@ static void resume (lua_State *L, void *ud) {
792 lua_assert(L->status == LUA_YIELD); 792 lua_assert(L->status == LUA_YIELD);
793 L->status = LUA_OK; /* mark that it is running (again) */ 793 L->status = LUA_OK; /* mark that it is running (again) */
794 if (isLua(ci)) { /* yielded inside a hook? */ 794 if (isLua(ci)) { /* yielded inside a hook? */
795 /* undo increment made by 'luaG_traceexec': instruction was not
796 executed yet */
797 lua_assert(ci->callstatus & CIST_HOOKYIELD);
798 ci->u.l.savedpc--;
795 L->top.p = firstArg; /* discard arguments */ 799 L->top.p = firstArg; /* discard arguments */
796 luaV_execute(L, ci); /* just continue running Lua code */ 800 luaV_execute(L, ci); /* just continue running Lua code */
797 } 801 }
diff --git a/src/3rdParty/lua/lgc.c b/src/3rdParty/lua/lgc.c
index 253a289..5817f9e 100644
--- a/src/3rdParty/lua/lgc.c
+++ b/src/3rdParty/lua/lgc.c
@@ -1713,7 +1713,7 @@ static void fullinc (lua_State *L, global_State *g) {
1713 /* finish any pending sweep phase to start a new cycle */ 1713 /* finish any pending sweep phase to start a new cycle */
1714 luaC_runtilstate(L, bitmask(GCSpause)); 1714 luaC_runtilstate(L, bitmask(GCSpause));
1715 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1715 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1716 g->gcstate = GCSenteratomic; /* go straight to atomic phase ??? */ 1716 g->gcstate = GCSenteratomic; /* go straight to atomic phase */
1717 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ 1717 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */
1718 /* estimate must be correct after a full GC cycle */ 1718 /* estimate must be correct after a full GC cycle */
1719 lua_assert(g->GCestimate == gettotalbytes(g)); 1719 lua_assert(g->GCestimate == gettotalbytes(g));
diff --git a/src/3rdParty/lua/liolib.c b/src/3rdParty/lua/liolib.c
index b08397d..c5075f3 100644
--- a/src/3rdParty/lua/liolib.c
+++ b/src/3rdParty/lua/liolib.c
@@ -245,8 +245,8 @@ static int f_gc (lua_State *L) {
245*/ 245*/
246static int io_fclose (lua_State *L) { 246static int io_fclose (lua_State *L) {
247 LStream *p = tolstream(L); 247 LStream *p = tolstream(L);
248 int res = fclose(p->f); 248 errno = 0;
249 return luaL_fileresult(L, (res == 0), NULL); 249 return luaL_fileresult(L, (fclose(p->f) == 0), NULL);
250} 250}
251 251
252 252
@@ -272,6 +272,7 @@ static int io_open (lua_State *L) {
272 LStream *p = newfile(L); 272 LStream *p = newfile(L);
273 const char *md = mode; /* to traverse/check mode */ 273 const char *md = mode; /* to traverse/check mode */
274 luaL_argcheck(L, l_checkmode(md), 2, "invalid mode"); 274 luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
275 errno = 0;
275 p->f = fopen(filename, mode); 276 p->f = fopen(filename, mode);
276 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; 277 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
277} 278}
@@ -292,6 +293,7 @@ static int io_popen (lua_State *L) {
292 const char *mode = luaL_optstring(L, 2, "r"); 293 const char *mode = luaL_optstring(L, 2, "r");
293 LStream *p = newprefile(L); 294 LStream *p = newprefile(L);
294 luaL_argcheck(L, l_checkmodep(mode), 2, "invalid mode"); 295 luaL_argcheck(L, l_checkmodep(mode), 2, "invalid mode");
296 errno = 0;
295 p->f = l_popen(L, filename, mode); 297 p->f = l_popen(L, filename, mode);
296 p->closef = &io_pclose; 298 p->closef = &io_pclose;
297 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; 299 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
@@ -300,6 +302,7 @@ static int io_popen (lua_State *L) {
300 302
301static int io_tmpfile (lua_State *L) { 303static int io_tmpfile (lua_State *L) {
302 LStream *p = newfile(L); 304 LStream *p = newfile(L);
305 errno = 0;
303 p->f = tmpfile(); 306 p->f = tmpfile();
304 return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; 307 return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
305} 308}
@@ -567,6 +570,7 @@ static int g_read (lua_State *L, FILE *f, int first) {
567 int nargs = lua_gettop(L) - 1; 570 int nargs = lua_gettop(L) - 1;
568 int n, success; 571 int n, success;
569 clearerr(f); 572 clearerr(f);
573 errno = 0;
570 if (nargs == 0) { /* no arguments? */ 574 if (nargs == 0) { /* no arguments? */
571 success = read_line(L, f, 1); 575 success = read_line(L, f, 1);
572 n = first + 1; /* to return 1 result */ 576 n = first + 1; /* to return 1 result */
@@ -660,6 +664,7 @@ static int io_readline (lua_State *L) {
660static int g_write (lua_State *L, FILE *f, int arg) { 664static int g_write (lua_State *L, FILE *f, int arg) {
661 int nargs = lua_gettop(L) - arg; 665 int nargs = lua_gettop(L) - arg;
662 int status = 1; 666 int status = 1;
667 errno = 0;
663 for (; nargs--; arg++) { 668 for (; nargs--; arg++) {
664 if (lua_type(L, arg) == LUA_TNUMBER) { 669 if (lua_type(L, arg) == LUA_TNUMBER) {
665 /* optimization: could be done exactly as for strings */ 670 /* optimization: could be done exactly as for strings */
@@ -678,7 +683,8 @@ static int g_write (lua_State *L, FILE *f, int arg) {
678 } 683 }
679 if (l_likely(status)) 684 if (l_likely(status))
680 return 1; /* file handle already on stack top */ 685 return 1; /* file handle already on stack top */
681 else return luaL_fileresult(L, status, NULL); 686 else
687 return luaL_fileresult(L, status, NULL);
682} 688}
683 689
684 690
@@ -703,6 +709,7 @@ static int f_seek (lua_State *L) {
703 l_seeknum offset = (l_seeknum)p3; 709 l_seeknum offset = (l_seeknum)p3;
704 luaL_argcheck(L, (lua_Integer)offset == p3, 3, 710 luaL_argcheck(L, (lua_Integer)offset == p3, 3,
705 "not an integer in proper range"); 711 "not an integer in proper range");
712 errno = 0;
706 op = l_fseek(f, offset, mode[op]); 713 op = l_fseek(f, offset, mode[op]);
707 if (l_unlikely(op)) 714 if (l_unlikely(op))
708 return luaL_fileresult(L, 0, NULL); /* error */ 715 return luaL_fileresult(L, 0, NULL); /* error */
@@ -719,19 +726,25 @@ static int f_setvbuf (lua_State *L) {
719 FILE *f = tofile(L); 726 FILE *f = tofile(L);
720 int op = luaL_checkoption(L, 2, NULL, modenames); 727 int op = luaL_checkoption(L, 2, NULL, modenames);
721 lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); 728 lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
722 int res = setvbuf(f, NULL, mode[op], (size_t)sz); 729 int res;
730 errno = 0;
731 res = setvbuf(f, NULL, mode[op], (size_t)sz);
723 return luaL_fileresult(L, res == 0, NULL); 732 return luaL_fileresult(L, res == 0, NULL);
724} 733}
725 734
726 735
727 736
728static int io_flush (lua_State *L) { 737static int io_flush (lua_State *L) {
729 return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); 738 FILE *f = getiofile(L, IO_OUTPUT);
739 errno = 0;
740 return luaL_fileresult(L, fflush(f) == 0, NULL);
730} 741}
731 742
732 743
733static int f_flush (lua_State *L) { 744static int f_flush (lua_State *L) {
734 return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); 745 FILE *f = tofile(L);
746 errno = 0;
747 return luaL_fileresult(L, fflush(f) == 0, NULL);
735} 748}
736 749
737 750
@@ -773,7 +786,7 @@ static const luaL_Reg meth[] = {
773** metamethods for file handles 786** metamethods for file handles
774*/ 787*/
775static const luaL_Reg metameth[] = { 788static const luaL_Reg metameth[] = {
776 {"__index", NULL}, /* place holder */ 789 {"__index", NULL}, /* placeholder */
777 {"__gc", f_gc}, 790 {"__gc", f_gc},
778 {"__close", f_gc}, 791 {"__close", f_gc},
779 {"__tostring", f_tostring}, 792 {"__tostring", f_tostring},
diff --git a/src/3rdParty/lua/lmathlib.c b/src/3rdParty/lua/lmathlib.c
index f140d62..4381063 100644
--- a/src/3rdParty/lua/lmathlib.c
+++ b/src/3rdParty/lua/lmathlib.c
@@ -352,7 +352,7 @@ static lua_Number I2d (Rand64 x) {
352 SRand64 sx = (SRand64)(trim64(x) >> shift64_FIG); 352 SRand64 sx = (SRand64)(trim64(x) >> shift64_FIG);
353 lua_Number res = (lua_Number)(sx) * scaleFIG; 353 lua_Number res = (lua_Number)(sx) * scaleFIG;
354 if (sx < 0) 354 if (sx < 0)
355 res += 1.0; /* correct the two's complement if negative */ 355 res += l_mathop(1.0); /* correct the two's complement if negative */
356 lua_assert(0 <= res && res < 1); 356 lua_assert(0 <= res && res < 1);
357 return res; 357 return res;
358} 358}
diff --git a/src/3rdParty/lua/loslib.c b/src/3rdParty/lua/loslib.c
index ad5a927..ba80d72 100644
--- a/src/3rdParty/lua/loslib.c
+++ b/src/3rdParty/lua/loslib.c
@@ -155,6 +155,7 @@ static int os_execute (lua_State *L) {
155 155
156static int os_remove (lua_State *L) { 156static int os_remove (lua_State *L) {
157 const char *filename = luaL_checkstring(L, 1); 157 const char *filename = luaL_checkstring(L, 1);
158 errno = 0;
158 return luaL_fileresult(L, remove(filename) == 0, filename); 159 return luaL_fileresult(L, remove(filename) == 0, filename);
159} 160}
160 161
@@ -162,6 +163,7 @@ static int os_remove (lua_State *L) {
162static int os_rename (lua_State *L) { 163static int os_rename (lua_State *L) {
163 const char *fromname = luaL_checkstring(L, 1); 164 const char *fromname = luaL_checkstring(L, 1);
164 const char *toname = luaL_checkstring(L, 2); 165 const char *toname = luaL_checkstring(L, 2);
166 errno = 0;
165 return luaL_fileresult(L, rename(fromname, toname) == 0, NULL); 167 return luaL_fileresult(L, rename(fromname, toname) == 0, NULL);
166} 168}
167 169
diff --git a/src/3rdParty/lua/lstring.c b/src/3rdParty/lua/lstring.c
index e921dd0..9775735 100644
--- a/src/3rdParty/lua/lstring.c
+++ b/src/3rdParty/lua/lstring.c
@@ -224,7 +224,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
224 return internshrstr(L, str, l); 224 return internshrstr(L, str, l);
225 else { 225 else {
226 TString *ts; 226 TString *ts;
227 if (l_unlikely(l >= (MAX_SIZE - sizeof(TString))/sizeof(char))) 227 if (l_unlikely(l * sizeof(char) >= (MAX_SIZE - sizeof(TString))))
228 luaM_toobig(L); 228 luaM_toobig(L);
229 ts = luaS_createlngstrobj(L, l); 229 ts = luaS_createlngstrobj(L, l);
230 memcpy(getlngstr(ts), str, l * sizeof(char)); 230 memcpy(getlngstr(ts), str, l * sizeof(char));
diff --git a/src/3rdParty/lua/lua.h b/src/3rdParty/lua/lua.h
index 040cc8e..f050dac 100644
--- a/src/3rdParty/lua/lua.h
+++ b/src/3rdParty/lua/lua.h
@@ -1,7 +1,7 @@
1/* 1/*
2** $Id: lua.h $ 2** $Id: lua.h $
3** Lua - A Scripting Language 3** Lua - A Scripting Language
4** Lua.org, PUC-Rio, Brazil (www.lua.org) 4** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
5** See Copyright Notice at the end of this file 5** See Copyright Notice at the end of this file
6*/ 6*/
7 7
@@ -13,19 +13,20 @@
13#include <stddef.h> 13#include <stddef.h>
14 14
15 15
16#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2023 Lua.org, PUC-Rio" 16#include "luaconf.h"
17#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
18
19 17
20#define LUA_VERSION_MAJOR_N 5
21#define LUA_VERSION_MINOR_N 4
22#define LUA_VERSION_RELEASE_N 6
23 18
24#define LUA_VERSION_NUM (LUA_VERSION_MAJOR_N * 100 + LUA_VERSION_MINOR_N) 19#define LUA_VERSION_MAJOR "5"
25#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + LUA_VERSION_RELEASE_N) 20#define LUA_VERSION_MINOR "4"
21#define LUA_VERSION_RELEASE "7"
26 22
23#define LUA_VERSION_NUM 504
24#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 7)
27 25
28#include "luaconf.h" 26#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
27#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
28#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2024 Lua.org, PUC-Rio"
29#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
29 30
30 31
31/* mark for precompiled code ('<esc>Lua') */ 32/* mark for precompiled code ('<esc>Lua') */
@@ -495,19 +496,8 @@ struct lua_Debug {
495/* }====================================================================== */ 496/* }====================================================================== */
496 497
497 498
498#define LUAI_TOSTRAUX(x) #x
499#define LUAI_TOSTR(x) LUAI_TOSTRAUX(x)
500
501#define LUA_VERSION_MAJOR LUAI_TOSTR(LUA_VERSION_MAJOR_N)
502#define LUA_VERSION_MINOR LUAI_TOSTR(LUA_VERSION_MINOR_N)
503#define LUA_VERSION_RELEASE LUAI_TOSTR(LUA_VERSION_RELEASE_N)
504
505#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
506#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
507
508
509/****************************************************************************** 499/******************************************************************************
510* Copyright (C) 1994-2023 Lua.org, PUC-Rio. 500* Copyright (C) 1994-2024 Lua.org, PUC-Rio.
511* 501*
512* Permission is hereby granted, free of charge, to any person obtaining 502* Permission is hereby granted, free of charge, to any person obtaining
513* a copy of this software and associated documentation files (the 503* a copy of this software and associated documentation files (the
diff --git a/src/3rdParty/lua/luaconf.h b/src/3rdParty/lua/luaconf.h
index acebe29..33bb580 100644
--- a/src/3rdParty/lua/luaconf.h
+++ b/src/3rdParty/lua/luaconf.h
@@ -261,7 +261,7 @@
261/* 261/*
262** LUA_IGMARK is a mark to ignore all after it when building the 262** LUA_IGMARK is a mark to ignore all after it when building the
263** module name (e.g., used to build the luaopen_ function name). 263** module name (e.g., used to build the luaopen_ function name).
264** Typically, the sufix after the mark is the module version, 264** Typically, the suffix after the mark is the module version,
265** as in "mod-v1.2.so". 265** as in "mod-v1.2.so".
266*/ 266*/
267#define LUA_IGMARK "-" 267#define LUA_IGMARK "-"
diff --git a/src/3rdParty/lua/lundump.h b/src/3rdParty/lua/lundump.h
index bc71ced..a97676c 100644
--- a/src/3rdParty/lua/lundump.h
+++ b/src/3rdParty/lua/lundump.h
@@ -21,7 +21,7 @@
21/* 21/*
22** Encode major-minor version in one byte, one nibble for each 22** Encode major-minor version in one byte, one nibble for each
23*/ 23*/
24#define LUAC_VERSION (LUA_VERSION_MAJOR_N*16+LUA_VERSION_MINOR_N) 24#define LUAC_VERSION (((LUA_VERSION_NUM / 100) * 16) + LUA_VERSION_NUM % 100)
25 25
26#define LUAC_FORMAT 0 /* this is the official format */ 26#define LUAC_FORMAT 0 /* this is the official format */
27 27
diff --git a/src/3rdParty/lua/lvm.c b/src/3rdParty/lua/lvm.c
index 4d71cff..fcd24e1 100644
--- a/src/3rdParty/lua/lvm.c
+++ b/src/3rdParty/lua/lvm.c
@@ -92,7 +92,7 @@ static int l_strton (const TValue *obj, TValue *result) {
92 if (!cvt2num(obj)) /* is object not a string? */ 92 if (!cvt2num(obj)) /* is object not a string? */
93 return 0; 93 return 0;
94 else { 94 else {
95 TString *st = tsvalue(obj); 95 TString *st = tsvalue(obj);
96 return (luaO_str2num(getstr(st), result) == tsslen(st) + 1); 96 return (luaO_str2num(getstr(st), result) == tsslen(st) + 1);
97 } 97 }
98} 98}
@@ -661,7 +661,7 @@ void luaV_concat (lua_State *L, int total) {
661 /* collect total length and number of strings */ 661 /* collect total length and number of strings */
662 for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) { 662 for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
663 size_t l = tsslen(tsvalue(s2v(top - n - 1))); 663 size_t l = tsslen(tsvalue(s2v(top - n - 1)));
664 if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) { 664 if (l_unlikely(l >= MAX_SIZE - sizeof(TString) - tl)) {
665 L->top.p = top - total; /* pop strings to avoid wasting stack */ 665 L->top.p = top - total; /* pop strings to avoid wasting stack */
666 luaG_runerror(L, "string length overflow"); 666 luaG_runerror(L, "string length overflow");
667 } 667 }
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp
index a454908..7f0dd07 100644
--- a/src/yuescript/yue_ast.cpp
+++ b/src/yuescript/yue_ast.cpp
@@ -490,7 +490,7 @@ std::string If_t::to_string(void* ud) const {
490std::string While_t::to_string(void* ud) const { 490std::string While_t::to_string(void* ud) const {
491 auto info = reinterpret_cast<YueFormat*>(ud); 491 auto info = reinterpret_cast<YueFormat*>(ud);
492 str_list temp{ 492 str_list temp{
493 type->to_string(ud) + ' ' + condition->to_string(ud)}; 493 type->to_string(ud) + ' ' + condition->to_string(ud) + (assignment ? assignment->to_string(ud) : std::string())};
494 if (body.is<Statement_t>()) { 494 if (body.is<Statement_t>()) {
495 temp.back() += " do "s + body->to_string(ud); 495 temp.back() += " do "s + body->to_string(ud);
496 } else { 496 } else {
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 8063517..92d67ac 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -337,8 +337,9 @@ AST_END(WhileType)
337AST_NODE(While) 337AST_NODE(While)
338 ast_ptr<true, WhileType_t> type; 338 ast_ptr<true, WhileType_t> type;
339 ast_ptr<true, Exp_t> condition; 339 ast_ptr<true, Exp_t> condition;
340 ast_ptr<false, Assignment_t> assignment;
340 ast_sel<true, Block_t, Statement_t> body; 341 ast_sel<true, Block_t, Statement_t> body;
341 AST_MEMBER(While, &type, &condition, &body) 342 AST_MEMBER(While, &type, &condition, &assignment, &body)
342AST_END(While) 343AST_END(While)
343 344
344AST_NODE(Repeat) 345AST_NODE(Repeat)
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index c29513e..77a4967 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -75,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = {
75 "close"s // Lua 5.4 75 "close"s // Lua 5.4
76}; 76};
77 77
78const std::string_view version = "0.25.5"sv; 78const std::string_view version = "0.25.6"sv;
79const std::string_view extension = "yue"sv; 79const std::string_view extension = "yue"sv;
80 80
81class CompileError : public std::logic_error { 81class CompileError : public std::logic_error {
@@ -1585,7 +1585,8 @@ private:
1585 } 1585 }
1586 goto metamethod53; 1586 goto metamethod53;
1587 } 1587 }
1588 case 504: { 1588 case 504:
1589 case 505: {
1589 if (name == "ipairs"sv) { 1590 if (name == "ipairs"sv) {
1590 throw CompileError("metamethod is not supported since Lua 5.4"sv, x); 1591 throw CompileError("metamethod is not supported since Lua 5.4"sv, x);
1591 } 1592 }
@@ -5038,7 +5039,7 @@ private:
5038#ifndef YUE_NO_MACRO 5039#ifndef YUE_NO_MACRO
5039 return LUA_VERSION_NUM; 5040 return LUA_VERSION_NUM;
5040#else 5041#else
5041 return 504; 5042 return 505;
5042#endif // YUE_NO_MACRO 5043#endif // YUE_NO_MACRO
5043 } 5044 }
5044 5045
@@ -8080,7 +8081,7 @@ private:
8080 } 8081 }
8081 8082
8082 void addDoToLastLineReturn(ast_node* body) { 8083 void addDoToLastLineReturn(ast_node* body) {
8083 if (auto block = ast_cast<Block_t>(body); body && !block->statements.empty()) { 8084 if (auto block = ast_cast<Block_t>(body); block && !block->statements.empty()) {
8084 auto last = static_cast<Statement_t*>(block->statements.back()); 8085 auto last = static_cast<Statement_t*>(block->statements.back());
8085 if (last->content.is<Return_t>()) { 8086 if (last->content.is<Return_t>()) {
8086 auto doNode = last->new_ptr<Do_t>(); 8087 auto doNode = last->new_ptr<Do_t>();
@@ -10271,6 +10272,34 @@ private:
10271 } 10272 }
10272 10273
10273 void transformWhile(While_t* whileNode, str_list& out) { 10274 void transformWhile(While_t* whileNode, str_list& out) {
10275 if (whileNode->assignment) {
10276 auto x = whileNode;
10277 auto repeat = x->new_ptr<Repeat_t>();
10278 repeat->condition.set(toAst<Exp_t>("false"sv, x));
10279 auto ifNode = x->new_ptr<If_t>();
10280 auto ifCond = x->new_ptr<IfCond_t>();
10281 bool isUntil = _parser.toString(whileNode->type) == "until"sv;
10282 ifNode->type.set(toAst<IfType_t>(isUntil ? "unless"sv : "if"sv, x));
10283 ifCond->condition.set(whileNode->condition);
10284 ifCond->assignment.set(whileNode->assignment);
10285 ifNode->nodes.push_back(ifCond);
10286 ifNode->nodes.push_back(whileNode->body);
10287 ifNode->nodes.push_back(toAst<Statement_t>("break"sv, x));
10288 auto simpleValue = x->new_ptr<SimpleValue_t>();
10289 simpleValue->value.set(ifNode);
10290 auto exp = newExp(simpleValue, x);
10291 auto expList = x->new_ptr<ExpList_t>();
10292 expList->exprs.push_back(exp);
10293 auto expListAssign = x->new_ptr<ExpListAssign_t>();
10294 expListAssign->expList.set(expList);
10295 auto stmt = x->new_ptr<Statement_t>();
10296 stmt->content.set(expListAssign);
10297 auto body = x->new_ptr<Body_t>();
10298 body->content.set(stmt);
10299 repeat->body.set(body);
10300 transformRepeat(repeat, out);
10301 return;
10302 }
10274 str_list temp; 10303 str_list temp;
10275 pushScope(); 10304 pushScope();
10276 bool isUntil = _parser.toString(whileNode->type) == "until"sv; 10305 bool isUntil = _parser.toString(whileNode->type) == "until"sv;
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index d7af780..c917255 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -383,7 +383,7 @@ YueParser::YueParser() {
383 If = IfType >> space >> IfCond >> space >> opt_body_with("then") >> *if_else_if >> -if_else; 383 If = IfType >> space >> IfCond >> space >> opt_body_with("then") >> *if_else_if >> -if_else;
384 384
385 WhileType = (expr("while") | "until") >> not_alpha_num; 385 WhileType = (expr("while") | "until") >> not_alpha_num;
386 While = WhileType >> space >> disable_do_chain_arg_table_block_rule(Exp) >> space >> opt_body_with("do"); 386 While = WhileType >> space >> disable_do_chain_arg_table_block_rule(Exp >> -(space >> Assignment)) >> space >> opt_body_with("do");
387 Repeat = key("repeat") >> space >> Body >> line_break >> *space_break >> check_indent_match >> space >> key("until") >> space >> Exp; 387 Repeat = key("repeat") >> space >> Body >> line_break >> *space_break >> check_indent_match >> space >> key("until") >> space >> Exp;
388 388
389 for_key = pl::user(key("for"), [](const item_t& item) { 389 for_key = pl::user(key("for"), [](const item_t& item) {