aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/inputs/attrib.yue2
-rw-r--r--spec/inputs/unicode/multiline_chain.yue6
-rw-r--r--spec/outputs/5.1/attrib.lua183
-rw-r--r--spec/outputs/assign.lua9
-rw-r--r--spec/outputs/attrib.lua1
-rw-r--r--spec/outputs/unicode/assign.lua9
-rw-r--r--spec/outputs/unicode/macro.lua26
-rw-r--r--spec/outputs/unicode/multiline_chain.lua35
-rw-r--r--spec/outputs/unicode/syntax.lua13
-rw-r--r--spec/outputs/unicode/vararg.lua488
-rw-r--r--spec/outputs/vararg.lua488
-rw-r--r--src/yuescript/yue_ast.cpp266
-rw-r--r--src/yuescript/yue_ast.h5
-rw-r--r--src/yuescript/yue_compiler.cpp604
-rw-r--r--src/yuescript/yue_compiler.h12
15 files changed, 1328 insertions, 819 deletions
diff --git a/spec/inputs/attrib.yue b/spec/inputs/attrib.yue
index 36aca99..f66f0db 100644
--- a/spec/inputs/attrib.yue
+++ b/spec/inputs/attrib.yue
@@ -41,6 +41,8 @@ do
41 41
42 close _ = <close>: -> print "first" 42 close _ = <close>: -> print "first"
43 43
44 print "third"
45
44_defers = setmetatable {}, __close: => 46_defers = setmetatable {}, __close: =>
45 @[#@]! 47 @[#@]!
46 @[#@] = nil 48 @[#@] = nil
diff --git a/spec/inputs/unicode/multiline_chain.yue b/spec/inputs/unicode/multiline_chain.yue
index 403f93b..6e8551c 100644
--- a/spec/inputs/unicode/multiline_chain.yue
+++ b/spec/inputs/unicode/multiline_chain.yue
@@ -21,8 +21,10 @@
21 21
22表bb = 22表bb =
23 键1: 变量a 23 键1: 变量a
24 \变量b 123 24 \变量b 123,
25 .变量c! 25 :字段A
26 .变量c 1, 2, 3
27 :字段B
26 键2: 28 键2:
27 键w1: 变量a! 29 键w1: 变量a!
28 .变量b 30 .变量b
diff --git a/spec/outputs/5.1/attrib.lua b/spec/outputs/5.1/attrib.lua
index 70e7e24..e28dca4 100644
--- a/spec/outputs/5.1/attrib.lua
+++ b/spec/outputs/5.1/attrib.lua
@@ -50,6 +50,22 @@ do
50 a, b = _obj_0[1], _obj_0[2] 50 a, b = _obj_0[1], _obj_0[2]
51 end 51 end
52end 52end
53local _anon_func_0 = function(f, error, _close_1, _arg_0, ...)
54 do
55 local _ok_0 = _arg_0
56 _close_1(f)
57 if _ok_0 then
58 return ...
59 else
60 return error(...)
61 end
62 end
63end
64local _anon_func_1 = function(io)
65 local _with_0 = io.open("file.txt")
66 _with_0:write("Hello")
67 return _with_0
68end
53do 69do
54 local v = (function() 70 local v = (function()
55 if flag then 71 if flag then
@@ -70,23 +86,43 @@ do
70 return error(...) 86 return error(...)
71 end 87 end
72 end)(pcall(function(...) 88 end)(pcall(function(...)
73 local f = (function() 89 local f = _anon_func_1(io)
74 local _with_0 = io.open("file.txt")
75 _with_0:write("Hello")
76 return _with_0
77 end)()
78 local _close_1 = assert(getmetatable(f).__close) 90 local _close_1 = assert(getmetatable(f).__close)
79 return (function(_arg_0, ...) 91 return _anon_func_0(f, error, _close_1, pcall(function(...) end, ...))
80 local _ok_0 = _arg_0
81 _close_1(f)
82 if _ok_0 then
83 return ...
84 else
85 return error(...)
86 end
87 end)(pcall(function(...) end, ...))
88 end, ...)) 92 end, ...))
89end 93end
94local _anon_func_2 = function(d, error, _close_1, _arg_0, ...)
95 do
96 local _ok_0 = _arg_0
97 _close_1(d)
98 if _ok_0 then
99 return ...
100 else
101 return error(...)
102 end
103 end
104end
105local _anon_func_3 = function(x)
106 if true then
107 if "abc" == x then
108 return 998
109 end
110 end
111end
112local _anon_func_5 = function(a, b)
113 if a ~= nil then
114 return a
115 else
116 return b
117 end
118end
119local _anon_func_4 = function(a, b)
120 if _anon_func_5(a, b) then
121 return {
122 value = value
123 }
124 end
125end
90do 126do
91 local a = (function() 127 local a = (function()
92 if true then 128 if true then
@@ -110,39 +146,34 @@ do
110 return error(...) 146 return error(...)
111 end 147 end
112 end)(pcall(function(...) 148 end)(pcall(function(...)
113 local c = (function() 149 local c = _anon_func_3(x)
114 if true then 150 local d = _anon_func_4(a, b)
115 local _exp_0 = x
116 if "abc" == _exp_0 then
117 return 998
118 end
119 end
120 end)()
121 local d = (function()
122 if (function()
123 if a ~= nil then
124 return a
125 else
126 return b
127 end
128 end)() then
129 return {
130 value = value
131 }
132 end
133 end)()
134 local _close_1 = assert(getmetatable(d).__close) 151 local _close_1 = assert(getmetatable(d).__close)
135 return (function(_arg_0, ...) 152 return _anon_func_2(d, error, _close_1, pcall(function(...) end, ...))
136 local _ok_0 = _arg_0
137 _close_1(d)
138 if _ok_0 then
139 return ...
140 else
141 return error(...)
142 end
143 end)(pcall(function(...) end, ...))
144 end, ...)) 153 end, ...))
145end 154end
155local _anon_func_6 = function(_, error, _close_1, _arg_0, ...)
156 do
157 local _ok_0 = _arg_0
158 _close_1(_)
159 if _ok_0 then
160 return ...
161 else
162 return error(...)
163 end
164 end
165end
166local _anon_func_7 = function(_, _close_2, error, _arg_0, ...)
167 do
168 local _ok_0 = _arg_0
169 _close_2(_)
170 if _ok_0 then
171 return ...
172 else
173 return error(...)
174 end
175 end
176end
146do 177do
147 local _ = (function() 178 local _ = (function()
148 local _with_0 = io.open("file.txt") 179 local _with_0 = io.open("file.txt")
@@ -165,30 +196,16 @@ do
165 end 196 end
166 }) 197 })
167 local _close_1 = assert(getmetatable(_).__close) 198 local _close_1 = assert(getmetatable(_).__close)
168 return (function(_arg_0, ...) 199 return _anon_func_6(_, error, _close_1, pcall(function(...)
169 local _ok_0 = _arg_0
170 _close_1(_)
171 if _ok_0 then
172 return ...
173 else
174 return error(...)
175 end
176 end)(pcall(function(...)
177 local _ = setmetatable({ }, { 200 local _ = setmetatable({ }, {
178 __close = function() 201 __close = function()
179 return print("first") 202 return print("first")
180 end 203 end
181 }) 204 })
182 local _close_2 = assert(getmetatable(_).__close) 205 local _close_2 = assert(getmetatable(_).__close)
183 return (function(_arg_0, ...) 206 return _anon_func_7(_, _close_2, error, pcall(function(...)
184 local _ok_0 = _arg_0 207 return print("third")
185 _close_2(_) 208 end, ...))
186 if _ok_0 then
187 return ...
188 else
189 return error(...)
190 end
191 end)(pcall(function(...) end, ...))
192 end, ...)) 209 end, ...))
193 end, ...)) 210 end, ...))
194end 211end
@@ -203,6 +220,28 @@ def = function(item)
203 _defers[#_defers + 1] = item 220 _defers[#_defers + 1] = item
204 return _defers 221 return _defers
205end 222end
223local _anon_func_8 = function(_, error, _close_1, _arg_0, ...)
224 do
225 local _ok_0 = _arg_0
226 _close_1(_)
227 if _ok_0 then
228 return ...
229 else
230 return error(...)
231 end
232 end
233end
234local _anon_func_9 = function(_, _close_2, error, _arg_0, ...)
235 do
236 local _ok_0 = _arg_0
237 _close_2(_)
238 if _ok_0 then
239 return ...
240 else
241 return error(...)
242 end
243 end
244end
206do 245do
207 local _ = def(function() 246 local _ = def(function()
208 return print(3) 247 return print(3)
@@ -221,28 +260,12 @@ do
221 return print(2) 260 return print(2)
222 end) 261 end)
223 local _close_1 = assert(getmetatable(_).__close) 262 local _close_1 = assert(getmetatable(_).__close)
224 return (function(_arg_0, ...) 263 return _anon_func_8(_, error, _close_1, pcall(function(...)
225 local _ok_0 = _arg_0
226 _close_1(_)
227 if _ok_0 then
228 return ...
229 else
230 return error(...)
231 end
232 end)(pcall(function(...)
233 local _ = def(function() 264 local _ = def(function()
234 return print(1) 265 return print(1)
235 end) 266 end)
236 local _close_2 = assert(getmetatable(_).__close) 267 local _close_2 = assert(getmetatable(_).__close)
237 return (function(_arg_0, ...) 268 return _anon_func_9(_, _close_2, error, pcall(function(...) end, ...))
238 local _ok_0 = _arg_0
239 _close_2(_)
240 if _ok_0 then
241 return ...
242 else
243 return error(...)
244 end
245 end)(pcall(function(...) end, ...))
246 end, ...)) 269 end, ...))
247 end, ...)) 270 end, ...))
248end 271end
diff --git a/spec/outputs/assign.lua b/spec/outputs/assign.lua
index 228e859..8bf7b35 100644
--- a/spec/outputs/assign.lua
+++ b/spec/outputs/assign.lua
@@ -42,11 +42,14 @@ do
42 end 42 end
43 end 43 end
44end 44end
45return _(function() 45local _anon_func_0 = function(print)
46 setmetatable(a, (function() 46 do
47 print(123) 47 print(123)
48 return { } 48 return { }
49 end)()) 49 end
50end
51return _(function()
52 setmetatable(a, _anon_func_0(print))
50 do 53 do
51 local a, b 54 local a, b
52 if "a" == c then 55 if "a" == c then
diff --git a/spec/outputs/attrib.lua b/spec/outputs/attrib.lua
index 181555f..07fc165 100644
--- a/spec/outputs/attrib.lua
+++ b/spec/outputs/attrib.lua
@@ -106,6 +106,7 @@ do
106 return print("first") 106 return print("first")
107 end 107 end
108 }) 108 })
109 print("third")
109end 110end
110local _defers = setmetatable({ }, { 111local _defers = setmetatable({ }, {
111 __close = function(self) 112 __close = function(self)
diff --git a/spec/outputs/unicode/assign.lua b/spec/outputs/unicode/assign.lua
index b530093..290b248 100644
--- a/spec/outputs/unicode/assign.lua
+++ b/spec/outputs/unicode/assign.lua
@@ -42,11 +42,14 @@ do
42 end 42 end
43 end 43 end
44end 44end
45return __u65e0_u6548_u53d8_u91cf(function() 45local _anon_func_0 = function(_u6253_u5370)
46 setmetatable(a_u53d8_u91cf, (function() 46 do
47 _u6253_u5370(123) 47 _u6253_u5370(123)
48 return { } 48 return { }
49 end)()) 49 end
50end
51return __u65e0_u6548_u53d8_u91cf(function()
52 setmetatable(a_u53d8_u91cf, _anon_func_0(_u6253_u5370))
50 do 53 do
51 local _u5143_u7d20a, _u5143_u7d20b 54 local _u5143_u7d20a, _u5143_u7d20b
52 do 55 do
diff --git a/spec/outputs/unicode/macro.lua b/spec/outputs/unicode/macro.lua
index 2ae5dce..88f6de7 100644
--- a/spec/outputs/unicode/macro.lua
+++ b/spec/outputs/unicode/macro.lua
@@ -211,11 +211,11 @@ local _call_1 = (_({
211 -2, 211 -2,
212 3 212 3
213})) 213}))
214_call_1 = _call_1["链"](_call_1, _call_1, _call_1, _call_1, _call_1, _call_1, _call_1, _call_1) 214_call_1 = _call_1["链"](_call_1)
215_call_1 = _call_1["映射"](_call_1, _call_1, _call_1, _call_1, function(self) 215_call_1 = _call_1["映射"](_call_1, function(self)
216 return self * 2 216 return self * 2
217end) 217end)
218_call_1 = _call_1["过滤"](_call_1, _call_1, function(self) 218_call_1 = _call_1["过滤"](_call_1, function(self)
219 return self > 3 219 return self > 3
220end) 220end)
221local _u7ed3_u679ca = _call_1["取值"](_call_1) 221local _u7ed3_u679ca = _call_1["取值"](_call_1)
@@ -227,25 +227,25 @@ local _call_2 = (_({
227 -2, 227 -2,
228 3 228 3
229})) 229}))
230_call_2 = _call_2["链"](_call_2, _call_2, _call_2, _call_2, _call_2, _call_2, _call_2, _call_2) 230_call_2 = _call_2["链"](_call_2)
231_call_2 = _call_2["映射"](_call_2, _call_2, _call_2, _call_2, function(self) 231_call_2 = _call_2["映射"](_call_2, function(self)
232 return self * 2 232 return self * 2
233end) 233end)
234_call_2 = _call_2["过滤"](_call_2, _call_2, function(self) 234_call_2 = _call_2["过滤"](_call_2, function(self)
235 return self > 3 235 return self > 3
236end) 236end)
237_call_2["每一个"](_call_2, function(self) 237_call_2["每一个"](_call_2, function(self)
238 return _u6253_u5370(self) 238 return _u6253_u5370(self)
239end) 239end)
240local _call_3 = _u539f_u70b9["变换"]["根节点"]["游戏对象"] 240local _call_3 = _u539f_u70b9["变换"]["根节点"]["游戏对象"]
241_call_3 = _call_3["父节点"](_call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3) 241_call_3 = _call_3["父节点"](_call_3)
242_call_3 = _call_3["后代"](_call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3) 242_call_3 = _call_3["后代"](_call_3)
243_call_3 = _call_3["选择启用"](_call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3) 243_call_3 = _call_3["选择启用"](_call_3)
244_call_3 = _call_3["选择可见"](_call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3, _call_3) 244_call_3 = _call_3["选择可见"](_call_3)
245_call_3 = _call_3["标签等于"](_call_3, _call_3, _call_3, _call_3, "fx") 245_call_3 = _call_3["标签等于"](_call_3, "fx")
246_call_3 = _call_3["其中"](_call_3, _call_3, function(x) 246_call_3 = _call_3["其中"](_call_3, function(x)
247 local _call_4 = x["名称"] 247 local _call_4 = x["名称"]
248 return _call_4["结尾为"](_call_4, _call_4, "(克隆)") 248 return _call_4["结尾为"](_call_4, "(克隆)")
249end) 249end)
250_u7ed3_u679c = _call_3["摧毁"](_call_3) 250_u7ed3_u679c = _call_3["摧毁"](_call_3)
251do 251do
diff --git a/spec/outputs/unicode/multiline_chain.lua b/spec/outputs/unicode/multiline_chain.lua
index 90fdf0b..f45e71f 100644
--- a/spec/outputs/unicode/multiline_chain.lua
+++ b/spec/outputs/unicode/multiline_chain.lua
@@ -24,7 +24,11 @@ end)(), {
24local _u8868bb = { 24local _u8868bb = {
25 ["键1"] = (function() 25 ["键1"] = (function()
26 local _call_1 = _u53d8_u91cfa 26 local _call_1 = _u53d8_u91cfa
27 return _call_1["变量b"](_call_1, 123)["变量c"]() 27 return (_call_1["变量b"](_call_1, 123, {
28 ["字段A"] = _u5b57_u6bb5A
29 }))["变量c"](1, 2, 3, {
30 ["字段B"] = _u5b57_u6bb5B
31 })
28 end)(), 32 end)(),
29 ["键2"] = { 33 ["键2"] = {
30 ["键w1"] = (function() 34 ["键w1"] = (function()
@@ -54,37 +58,40 @@ _u51fd_u6570 = function()
54 end 58 end
55 return _accum_0 59 return _accum_0
56end 60end
61local _anon_func_0 = function(_u53d8_u91cfa)
62 do
63 local _call_1 = _u53d8_u91cfa
64 return (_call_1["变量b"](_call_1, 123))["变量c"]("abc")
65 end
66end
57local _u51fd_u65701 67local _u51fd_u65701
58_u51fd_u65701 = function() 68_u51fd_u65701 = function()
59 return _u53d8_u91cfx, (function() 69 return _u53d8_u91cfx, _anon_func_0(_u53d8_u91cfa)
60 local _call_1 = _u53d8_u91cfa
61 return _call_1["变量b"](_call_1, 123)["变量c"]("abc")
62 end)()
63end 70end
64local _call_1 = _u539f_u59cb["转换"].root.gameObject 71local _call_1 = _u539f_u59cb["转换"].root.gameObject
65local _call_2 = _call_1["父节点"](_call_1) 72local _call_2 = _call_1["父节点"](_call_1)
66local _call_3 = _call_2["后代节点"](_call_2) 73local _call_3 = _call_2["后代节点"](_call_2)
67local _call_4 = _call_3["选择启用"](_call_3) 74local _call_4 = _call_3["选择启用"](_call_3)
68local _call_5 = _call_4["选择可见"](_call_4) 75local _call_5 = _call_4["选择可见"](_call_4)
69local _call_6 = _call_5["标签相等"](_call_5, "fx") 76local _call_6 = (_call_5["标签相等"](_call_5, "fx"))
70local _call_7 = _call_6["筛选"](_call_6, function(_u5143_u7d20) 77local _call_7 = (_call_6["筛选"](_call_6, function(_u5143_u7d20)
71 if _u5143_u7d20["是否目标"](_u5143_u7d20, _u5143_u7d20) then 78 if _u5143_u7d20["是否目标"](_u5143_u7d20) then
72 return false 79 return false
73 end 80 end
74 local _call_7 = _u5143_u7d20["名称"] 81 local _call_7 = _u5143_u7d20["名称"]
75 return _call_7["结束于"](_call_7, _call_7, "(Clone)") 82 return _call_7["结束于"](_call_7, "(Clone)")
76end) 83end))
77local _u7ed3_u679c = _call_7["销毁"](_call_7) 84local _u7ed3_u679c = _call_7["销毁"](_call_7)
78local _call_8 = _u539f_u70b9["变换"]["根节点"]["游戏对象"] 85local _call_8 = _u539f_u70b9["变换"]["根节点"]["游戏对象"]
79local _call_9 = _call_8["父节点"](_call_8) 86local _call_9 = _call_8["父节点"](_call_8)
80local _call_10 = _call_9["后代节点"](_call_9) 87local _call_10 = _call_9["后代节点"](_call_9)
81local _call_11 = _call_10["选择启用"](_call_10) 88local _call_11 = _call_10["选择启用"](_call_10)
82local _call_12 = _call_11["选择可见"](_call_11) 89local _call_12 = _call_11["选择可见"](_call_11)
83local _call_13 = _call_12["标签相等"](_call_12, "fx") 90local _call_13 = (_call_12["标签相等"](_call_12, "fx"))
84local _call_14 = _call_13["筛选"](_call_13, function(_u5143_u7d20) 91local _call_14 = (_call_13["筛选"](_call_13, function(_u5143_u7d20)
85 local _call_14 = _u5143_u7d20["名称"] 92 local _call_14 = _u5143_u7d20["名称"]
86 return _call_14["结束于"](_call_14, _call_14, "(Clone)") 93 return _call_14["结束于"](_call_14, "(Clone)")
87end) 94end))
88_call_14["销毁"](_call_14) 95_call_14["销毁"](_call_14)
89do 96do
90 local _with_0 = _u9879_u76ee 97 local _with_0 = _u9879_u76ee
diff --git a/spec/outputs/unicode/syntax.lua b/spec/outputs/unicode/syntax.lua
index 664fa46..f086db6 100644
--- a/spec/outputs/unicode/syntax.lua
+++ b/spec/outputs/unicode/syntax.lua
@@ -282,13 +282,16 @@ _ = 5 + _u4ec0_u4e48(_u65e0_u804a)
282_u4ec0_u4e48(_u65e0_u804a + 5) 282_u4ec0_u4e48(_u65e0_u804a + 5)
283_ = 5 - _u4ec0_u4e48(_u65e0_u804a) 283_ = 5 - _u4ec0_u4e48(_u65e0_u804a)
284_u4ec0_u4e48(_u65e0_u804a - 5) 284_u4ec0_u4e48(_u65e0_u804a - 5)
285_u53d8_u91cfx = _u4f60_u597d - _u4e16_u754c - _u67d0_u7269; 285_u53d8_u91cfx = _u4f60_u597d - _u4e16_u754c - _u67d0_u7269
286local _anon_func_0 = function(_u4ec0_u4e48)
287 do
288 local _call_8 = _u4ec0_u4e48
289 return _call_8["酷"](_call_8, 100)
290 end
291end
286(function(_u67d0_u7269) 292(function(_u67d0_u7269)
287 if _u67d0_u7269 == nil then 293 if _u67d0_u7269 == nil then
288 _u67d0_u7269 = _u4e0e((function() 294 _u67d0_u7269 = _u4e0e(_anon_func_0(_u4ec0_u4e48))
289 local _call_8 = _u4ec0_u4e48
290 return _call_8["酷"](_call_8, 100)
291 end)())
292 end 295 end
293 return _u6253_u5370(_u67d0_u7269) 296 return _u6253_u5370(_u67d0_u7269)
294end)() 297end)()
diff --git a/spec/outputs/unicode/vararg.lua b/spec/outputs/unicode/vararg.lua
index 41d1bfd..39fbf0c 100644
--- a/spec/outputs/unicode/vararg.lua
+++ b/spec/outputs/unicode/vararg.lua
@@ -1,211 +1,264 @@
1local _u8fde_u63a5 1local _anon_func_0 = function(_u53d8_u91cfa)
2_u8fde_u63a5 = function(...) 2 _u53d8_u91cfa["函数"](_u53d8_u91cfa)
3 _u5e26_u6709((function() 3 return _u53d8_u91cfa
4 local _with_0 = _u53d8_u91cfa 4end
5 _with_0["函数"](_with_0) 5local _anon_func_1 = function(_u53d8_u91cfa, ...)
6 return _with_0 6 _u53d8_u91cfa["函数"](_u53d8_u91cfa, ...)
7 end)()) 7 return _u53d8_u91cfa
8 _u5e26_u6709((function(...) 8end
9 local _with_0 = _u53d8_u91cfa 9local _anon_func_2 = function(_u9879_u76ee)
10 _with_0["函数"](_with_0, ...) 10 local _accum_0 = { }
11 return _with_0 11 local _len_0 = 1
12 end)(...)) 12 for i = 1, 10 do
13 _u5217_u8868_u751f_u6210((function() 13 _accum_0[_len_0] = _u9879_u76ee[i]
14 local _accum_0 = { } 14 _len_0 = _len_0 + 1
15 local _len_0 = 1 15 end
16 for i = 1, 10 do 16 return _accum_0
17 _accum_0[_len_0] = _u9879_u76ee[i] 17end
18 _len_0 = _len_0 + 1 18local _anon_func_3 = function(_u9879_u76ee, ...)
19 end 19 local _accum_0 = { }
20 return _accum_0 20 local _len_0 = 1
21 end)()) 21 for i = 1, 10 do
22 _u5217_u8868_u751f_u6210((function(...) 22 _accum_0[_len_0] = _u9879_u76ee[i](...)
23 local _accum_0 = { } 23 _len_0 = _len_0 + 1
24 local _len_0 = 1 24 end
25 for i = 1, 10 do 25 return _accum_0
26 _accum_0[_len_0] = _u9879_u76ee[i](...) 26end
27 _len_0 = _len_0 + 1 27local _anon_func_4 = function(_u9879_u76ee)
28 end 28 local _accum_0 = { }
29 return _accum_0 29 local _len_0 = 1
30 end)(...)) 30 for _index_0 = 1, #_u9879_u76ee do
31 _u5217_u8868_u751f_u6210((function() 31 local _u7269_u54c1 = _u9879_u76ee[_index_0]
32 local _accum_0 = { } 32 _accum_0[_len_0] = _u7269_u54c1
33 local _len_0 = 1 33 _len_0 = _len_0 + 1
34 local _list_0 = _u9879_u76ee 34 end
35 for _index_0 = 1, #_list_0 do 35 return _accum_0
36 local _u7269_u54c1 = _list_0[_index_0] 36end
37 _accum_0[_len_0] = _u7269_u54c1 37local _anon_func_5 = function(_u9879_u76ee, ...)
38 _len_0 = _len_0 + 1 38 local _accum_0 = { }
39 end 39 local _len_0 = 1
40 return _accum_0 40 for _index_0 = 1, #_u9879_u76ee do
41 end)()) 41 local _u7269_u54c1 = _u9879_u76ee[_index_0]
42 _u5217_u8868_u751f_u6210((function(...) 42 _accum_0[_len_0] = _u7269_u54c1(...)
43 local _accum_0 = { } 43 _len_0 = _len_0 + 1
44 local _len_0 = 1 44 end
45 local _list_0 = _u9879_u76ee 45 return _accum_0
46 for _index_0 = 1, #_list_0 do 46end
47 local _u7269_u54c1 = _list_0[_index_0] 47local _anon_func_6 = function(setmetatable, _u51fd_u6570)
48 _accum_0[_len_0] = _u7269_u54c1(...) 48 local _u53d8_u91cfA
49 _len_0 = _len_0 + 1 49 do
50 local _class_0
51 local _base_0 = { }
52 if _base_0.__index == nil then
53 _base_0.__index = _base_0
50 end 54 end
51 return _accum_0 55 _class_0 = setmetatable({
52 end)(...)) 56 __init = function() end,
53 _u7c7b_u751f_u6210((function() 57 __base = _base_0,
54 local _u53d8_u91cfA 58 __name = "变量A"
55 do 59 }, {
56 local _class_0 60 __index = _base_0,
57 local _base_0 = { } 61 __call = function(cls, ...)
58 if _base_0.__index == nil then 62 local _self_0 = setmetatable({ }, _base_0)
59 _base_0.__index = _base_0 63 cls.__init(_self_0, ...)
64 return _self_0
60 end 65 end
61 _class_0 = setmetatable({ 66 })
62 __init = function() end, 67 _base_0.__class = _class_0
63 __base = _base_0, 68 local self = _class_0;
64 __name = "变量A" 69 _u51fd_u6570()
65 }, { 70 _u53d8_u91cfA = _class_0
66 __index = _base_0, 71 return _class_0
67 __call = function(cls, ...) 72 end
68 local _self_0 = setmetatable({ }, _base_0) 73end
69 cls.__init(_self_0, ...) 74local _anon_func_7 = function(setmetatable, _u51fd_u6570, ...)
70 return _self_0 75 local _u53d8_u91cfA
71 end 76 do
72 }) 77 local _class_0
73 _base_0.__class = _class_0 78 local _base_0 = { }
74 local self = _class_0; 79 if _base_0.__index == nil then
75 _u51fd_u6570() 80 _base_0.__index = _base_0
76 _u53d8_u91cfA = _class_0
77 return _class_0
78 end 81 end
79 end)()) 82 _class_0 = setmetatable({
80 _u7c7b_u751f_u6210((function(...) 83 __init = function() end,
81 local _u53d8_u91cfA 84 __base = _base_0,
82 do 85 __name = "变量A"
83 local _class_0 86 }, {
84 local _base_0 = { } 87 __index = _base_0,
85 if _base_0.__index == nil then 88 __call = function(cls, ...)
86 _base_0.__index = _base_0 89 local _self_0 = setmetatable({ }, _base_0)
90 cls.__init(_self_0, ...)
91 return _self_0
87 end 92 end
88 _class_0 = setmetatable({ 93 })
89 __init = function() end, 94 _base_0.__class = _class_0
90 __base = _base_0, 95 local self = _class_0;
91 __name = "变量A" 96 _u51fd_u6570(...)
92 }, { 97 _u53d8_u91cfA = _class_0
93 __index = _base_0, 98 return _class_0
94 __call = function(cls, ...) 99 end
95 local _self_0 = setmetatable({ }, _base_0) 100end
96 cls.__init(_self_0, ...) 101local _anon_func_8 = function(pairs, _u8868)
97 return _self_0 102 local _tbl_0 = { }
98 end 103 for _u952e, _u503c in pairs(_u8868) do
99 }) 104 _tbl_0[_u952e] = _u503c
100 _base_0.__class = _class_0 105 end
101 local self = _class_0; 106 return _tbl_0
102 _u51fd_u6570(...) 107end
103 _u53d8_u91cfA = _class_0 108local _anon_func_9 = function(pairs, _u8868, ...)
104 return _class_0 109 local _tbl_0 = { }
105 end 110 for _u952e, _u503c in pairs(_u8868) do
106 end)(...)) 111 _tbl_0[_u952e] = _u503c(...)
107 _u8868_u751f_u6210((function() 112 end
108 local _tbl_0 = { } 113 return _tbl_0
109 for _u952e, _u503c in pairs(_u8868) do 114end
110 _tbl_0[_u952e] = _u503c 115local _anon_func_10 = function(_u9879_u76ee)
111 end 116 local _tbl_0 = { }
112 return _tbl_0 117 for _index_0 = 1, #_u9879_u76ee do
113 end)()) 118 local _u7269_u54c1 = _u9879_u76ee[_index_0]
114 _u8868_u751f_u6210((function(...) 119 _tbl_0[_u7269_u54c1] = true
115 local _tbl_0 = { } 120 end
116 for _u952e, _u503c in pairs(_u8868) do 121 return _tbl_0
117 _tbl_0[_u952e] = _u503c(...) 122end
118 end 123local _anon_func_11 = function(_u9879_u76ee, ...)
119 return _tbl_0 124 local _tbl_0 = { }
120 end)(...)) 125 for _index_0 = 1, #_u9879_u76ee do
121 _u8868_u751f_u6210((function() 126 local _u7269_u54c1 = _u9879_u76ee[_index_0]
122 local _tbl_0 = { } 127 _tbl_0[_u7269_u54c1(...)] = true
123 local _list_0 = _u9879_u76ee 128 end
124 for _index_0 = 1, #_list_0 do 129 return _tbl_0
125 local _u7269_u54c1 = _list_0[_index_0] 130end
126 _tbl_0[_u7269_u54c1] = true 131local _anon_func_12 = function(_u51fd_u6570)
127 end 132 do
128 return _tbl_0
129 end)())
130 _u8868_u751f_u6210((function(...)
131 local _tbl_0 = { }
132 local _list_0 = _u9879_u76ee
133 for _index_0 = 1, #_list_0 do
134 local _u7269_u54c1 = _list_0[_index_0]
135 _tbl_0[_u7269_u54c1(...)] = true
136 end
137 return _tbl_0
138 end)(...))
139 _u505a_u64cd_u4f5c((function()
140 return _u51fd_u6570() 133 return _u51fd_u6570()
141 end)()) 134 end
142 _u505a_u64cd_u4f5c((function(...) 135end
136local _anon_func_13 = function(_u51fd_u6570, ...)
137 do
143 return _u51fd_u6570(...) 138 return _u51fd_u6570(...)
144 end)(...)) 139 end
145 _u5f53_u64cd_u4f5c((function() 140end
146 local _accum_0 = { } 141local _anon_func_14 = function(_u51fd_u6570)
147 local _len_0 = 1 142 local _accum_0 = { }
148 while false do 143 local _len_0 = 1
149 _accum_0[_len_0] = _u51fd_u6570() 144 while false do
150 _len_0 = _len_0 + 1 145 _accum_0[_len_0] = _u51fd_u6570()
151 end 146 _len_0 = _len_0 + 1
152 return _accum_0 147 end
153 end)()) 148 return _accum_0
154 _u5f53_u64cd_u4f5c((function(...) 149end
155 local _accum_0 = { } 150local _anon_func_15 = function(_u51fd_u6570, ...)
156 local _len_0 = 1 151 local _accum_0 = { }
157 while false do 152 local _len_0 = 1
158 _accum_0[_len_0] = _u51fd_u6570(...) 153 while false do
159 _len_0 = _len_0 + 1 154 _accum_0[_len_0] = _u51fd_u6570(...)
160 end 155 _len_0 = _len_0 + 1
161 return _accum_0 156 end
162 end)(...)) 157 return _accum_0
163 _u5982_u679c_u64cd_u4f5c((function() 158end
164 if false then 159local _anon_func_16 = function(_u51fd_u6570)
165 return _u51fd_u6570() 160 if false then
166 end 161 return _u51fd_u6570()
167 end)()) 162 end
168 _u5982_u679c_u64cd_u4f5c((function(...) 163end
169 if false then 164local _anon_func_17 = function(_u51fd_u6570, ...)
170 return _u51fd_u6570(...) 165 if false then
171 end 166 return _u51fd_u6570(...)
172 end)(...)) 167 end
173 _u9664_u975e_u64cd_u4f5c((function() 168end
174 if not true then 169local _anon_func_18 = function(_u51fd_u6570)
175 return _u51fd_u6570() 170 if not true then
176 end 171 return _u51fd_u6570()
177 end)()) 172 end
178 _u9664_u975e_u64cd_u4f5c((function(...) 173end
179 if not true then 174local _anon_func_19 = function(_u51fd_u6570, ...)
180 return _u51fd_u6570(...) 175 if not true then
181 end 176 return _u51fd_u6570(...)
182 end)(...)) 177 end
183 _u5207_u6362_u64cd_u4f5c((function() 178end
184 local _exp_0 = _u53d8_u91cfx 179local _anon_func_20 = function(_u53d8_u91cfx, _u51fd_u6570)
185 if "abc" == _exp_0 then 180 if "abc" == _u53d8_u91cfx then
186 return _u51fd_u6570() 181 return _u51fd_u6570()
187 end 182 end
188 end)()) 183end
189 _u5207_u6362_u64cd_u4f5c((function(...) 184local _anon_func_21 = function(_u53d8_u91cfx, _u51fd_u6570, ...)
190 local _exp_0 = _u53d8_u91cfx 185 if "abc" == _u53d8_u91cfx then
191 if "abc" == _exp_0 then 186 return _u51fd_u6570(...)
192 return _u51fd_u6570(...) 187 end
193 end 188end
194 end)(...)) 189local _anon_func_22 = function(_u51fd_u6570)
195 _u8868_u8fbe_u5f0f_u64cd_u4f5c((function() 190 if _u51fd_u6570 ~= nil then
196 local _obj_0 = _u51fd_u6570 191 return _u51fd_u6570()
197 if _obj_0 ~= nil then 192 end
198 return _obj_0() 193 return nil
199 end 194end
200 return nil 195local _anon_func_23 = function(_u51fd_u6570, ...)
201 end)()) 196 if _u51fd_u6570 ~= nil then
202 _u8868_u8fbe_u5f0f_u64cd_u4f5c((function(...) 197 return _u51fd_u6570(...)
203 local _obj_0 = _u51fd_u6570 198 end
204 if _obj_0 ~= nil then 199 return nil
205 return _obj_0(...) 200end
206 end 201local _anon_func_24 = function(select, _u6253_u5370, ...)
207 return nil 202 do
208 end)(...)) 203 _u6253_u5370(select("#", ...))
204 return _u6253_u5370(...)
205 end
206end
207local _anon_func_25 = function(_u6253_u5370, ...)
208 do
209 return _u6253_u5370(...)
210 end
211end
212local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682)
213 if 1 == _u53d8_u91cfx then
214 _u8868["变量x"] = 123
215 return _u8868
216 else
217 return _u88682
218 end
219end
220local _anon_func_27 = function(_u6253_u5370, ...)
221 do
222 return _u6253_u5370(...)
223 end
224end
225local _anon_func_28 = function(_u6761_u4ef6)
226 if _u6761_u4ef6 then
227 return 3, 4, 5
228 end
229end
230local _anon_func_29 = function(_u6253_u5370, _arg_0, ...)
231 do
232 local _u8868 = _arg_0
233 return _u6253_u5370(...)
234 end
235end
236local _u8fde_u63a5
237_u8fde_u63a5 = function(...)
238 _u5e26_u6709(_anon_func_0(_u53d8_u91cfa))
239 _u5e26_u6709(_anon_func_1(_u53d8_u91cfa, ...))
240 _u5217_u8868_u751f_u6210(_anon_func_2(_u9879_u76ee))
241 _u5217_u8868_u751f_u6210(_anon_func_3(_u9879_u76ee, ...))
242 _u5217_u8868_u751f_u6210(_anon_func_4(_u9879_u76ee))
243 _u5217_u8868_u751f_u6210(_anon_func_5(_u9879_u76ee, ...))
244 _u7c7b_u751f_u6210(_anon_func_6(setmetatable, _u51fd_u6570))
245 _u7c7b_u751f_u6210(_anon_func_7(setmetatable, _u51fd_u6570, ...))
246 _u8868_u751f_u6210(_anon_func_8(pairs, _u8868))
247 _u8868_u751f_u6210(_anon_func_9(pairs, _u8868, ...))
248 _u8868_u751f_u6210(_anon_func_10(_u9879_u76ee))
249 _u8868_u751f_u6210(_anon_func_11(_u9879_u76ee, ...))
250 _u505a_u64cd_u4f5c(_anon_func_12(_u51fd_u6570))
251 _u505a_u64cd_u4f5c(_anon_func_13(_u51fd_u6570, ...))
252 _u5f53_u64cd_u4f5c(_anon_func_14(_u51fd_u6570))
253 _u5f53_u64cd_u4f5c(_anon_func_15(_u51fd_u6570, ...))
254 _u5982_u679c_u64cd_u4f5c(_anon_func_16(_u51fd_u6570))
255 _u5982_u679c_u64cd_u4f5c(_anon_func_17(_u51fd_u6570, ...))
256 _u9664_u975e_u64cd_u4f5c(_anon_func_18(_u51fd_u6570))
257 _u9664_u975e_u64cd_u4f5c(_anon_func_19(_u51fd_u6570, ...))
258 _u5207_u6362_u64cd_u4f5c(_anon_func_20(_u53d8_u91cfx, _u51fd_u6570))
259 _u5207_u6362_u64cd_u4f5c(_anon_func_21(_u53d8_u91cfx, _u51fd_u6570, ...))
260 _u8868_u8fbe_u5f0f_u64cd_u4f5c(_anon_func_22(_u51fd_u6570))
261 _u8868_u8fbe_u5f0f_u64cd_u4f5c(_anon_func_23(_u51fd_u6570, ...))
209 _u5192_u53f7((function() 262 _u5192_u53f7((function()
210 local _base_0 = f() 263 local _base_0 = f()
211 local _fn_0 = _base_0["函数"] 264 local _fn_0 = _base_0["函数"]
@@ -240,40 +293,17 @@ _u8fde_u63a5 = function(...)
240 _u591a_u53c2_u6570_u51fd_u6570 = function() 293 _u591a_u53c2_u6570_u51fd_u6570 = function()
241 return 10, nil, 20, nil, 30 294 return 10, nil, 20, nil, 30
242 end 295 end
243 return (function(...) 296 return _anon_func_24(select, _u6253_u5370, _u591a_u53c2_u6570_u51fd_u6570())
244 _u6253_u5370(select("#", ...))
245 return _u6253_u5370(...)
246 end)(_u591a_u53c2_u6570_u51fd_u6570())
247 end)(_u51fd_u6570_u540d(true)) 297 end)(_u51fd_u6570_u540d(true))
248 end 298 end
249 do 299 do
250 (function(...) 300 _anon_func_25(_u6253_u5370, _anon_func_26(_u53d8_u91cfx, _u8868, _u88682))
251 return _u6253_u5370(...)
252 end)((function()
253 local _exp_0 = _u53d8_u91cfx
254 if 1 == _exp_0 then
255 local _with_0 = _u8868
256 _with_0["变量x"] = 123
257 return _with_0
258 else
259 return _u88682
260 end
261 end)())
262 end 301 end
263 do 302 do
264 (function(...) 303 _anon_func_27(_u6253_u5370, 1, 2, _anon_func_28(_u6761_u4ef6))
265 return _u6253_u5370(...)
266 end)(1, 2, (function()
267 if _u6761_u4ef6 then
268 return 3, 4, 5
269 end
270 end)())
271 end 304 end
272 do 305 do
273 (function(_arg_0, ...) 306 _anon_func_29(_u6253_u5370, {
274 local _u8868 = _arg_0
275 return _u6253_u5370(...)
276 end)({
277 ["名字"] = "abc", 307 ["名字"] = "abc",
278 ["值"] = 123 308 ["值"] = 123
279 }) 309 })
diff --git a/spec/outputs/vararg.lua b/spec/outputs/vararg.lua
index ea40da1..39becd4 100644
--- a/spec/outputs/vararg.lua
+++ b/spec/outputs/vararg.lua
@@ -1,211 +1,264 @@
1local join 1local _anon_func_0 = function(a)
2join = function(...) 2 a:func()
3 f_with((function() 3 return a
4 local _with_0 = a 4end
5 _with_0:func() 5local _anon_func_1 = function(a, ...)
6 return _with_0 6 a:func(...)
7 end)()) 7 return a
8 f_with((function(...) 8end
9 local _with_0 = a 9local _anon_func_2 = function(items)
10 _with_0:func(...) 10 local _accum_0 = { }
11 return _with_0 11 local _len_0 = 1
12 end)(...)) 12 for i = 1, 10 do
13 f_listcomp((function() 13 _accum_0[_len_0] = items[i]
14 local _accum_0 = { } 14 _len_0 = _len_0 + 1
15 local _len_0 = 1 15 end
16 for i = 1, 10 do 16 return _accum_0
17 _accum_0[_len_0] = items[i] 17end
18 _len_0 = _len_0 + 1 18local _anon_func_3 = function(items, ...)
19 end 19 local _accum_0 = { }
20 return _accum_0 20 local _len_0 = 1
21 end)()) 21 for i = 1, 10 do
22 f_listcomp((function(...) 22 _accum_0[_len_0] = items[i](...)
23 local _accum_0 = { } 23 _len_0 = _len_0 + 1
24 local _len_0 = 1 24 end
25 for i = 1, 10 do 25 return _accum_0
26 _accum_0[_len_0] = items[i](...) 26end
27 _len_0 = _len_0 + 1 27local _anon_func_4 = function(items)
28 end 28 local _accum_0 = { }
29 return _accum_0 29 local _len_0 = 1
30 end)(...)) 30 for _index_0 = 1, #items do
31 f_listcomp((function() 31 local item = items[_index_0]
32 local _accum_0 = { } 32 _accum_0[_len_0] = item
33 local _len_0 = 1 33 _len_0 = _len_0 + 1
34 local _list_0 = items 34 end
35 for _index_0 = 1, #_list_0 do 35 return _accum_0
36 local item = _list_0[_index_0] 36end
37 _accum_0[_len_0] = item 37local _anon_func_5 = function(items, ...)
38 _len_0 = _len_0 + 1 38 local _accum_0 = { }
39 end 39 local _len_0 = 1
40 return _accum_0 40 for _index_0 = 1, #items do
41 end)()) 41 local item = items[_index_0]
42 f_listcomp((function(...) 42 _accum_0[_len_0] = item(...)
43 local _accum_0 = { } 43 _len_0 = _len_0 + 1
44 local _len_0 = 1 44 end
45 local _list_0 = items 45 return _accum_0
46 for _index_0 = 1, #_list_0 do 46end
47 local item = _list_0[_index_0] 47local _anon_func_6 = function(setmetatable, func)
48 _accum_0[_len_0] = item(...) 48 local A
49 _len_0 = _len_0 + 1 49 do
50 local _class_0
51 local _base_0 = { }
52 if _base_0.__index == nil then
53 _base_0.__index = _base_0
50 end 54 end
51 return _accum_0 55 _class_0 = setmetatable({
52 end)(...)) 56 __init = function() end,
53 f_class((function() 57 __base = _base_0,
54 local A 58 __name = "A"
55 do 59 }, {
56 local _class_0 60 __index = _base_0,
57 local _base_0 = { } 61 __call = function(cls, ...)
58 if _base_0.__index == nil then 62 local _self_0 = setmetatable({ }, _base_0)
59 _base_0.__index = _base_0 63 cls.__init(_self_0, ...)
64 return _self_0
60 end 65 end
61 _class_0 = setmetatable({ 66 })
62 __init = function() end, 67 _base_0.__class = _class_0
63 __base = _base_0, 68 local self = _class_0;
64 __name = "A" 69 func()
65 }, { 70 A = _class_0
66 __index = _base_0, 71 return _class_0
67 __call = function(cls, ...) 72 end
68 local _self_0 = setmetatable({ }, _base_0) 73end
69 cls.__init(_self_0, ...) 74local _anon_func_7 = function(setmetatable, func, ...)
70 return _self_0 75 local A
71 end 76 do
72 }) 77 local _class_0
73 _base_0.__class = _class_0 78 local _base_0 = { }
74 local self = _class_0; 79 if _base_0.__index == nil then
75 func() 80 _base_0.__index = _base_0
76 A = _class_0
77 return _class_0
78 end 81 end
79 end)()) 82 _class_0 = setmetatable({
80 f_class((function(...) 83 __init = function() end,
81 local A 84 __base = _base_0,
82 do 85 __name = "A"
83 local _class_0 86 }, {
84 local _base_0 = { } 87 __index = _base_0,
85 if _base_0.__index == nil then 88 __call = function(cls, ...)
86 _base_0.__index = _base_0 89 local _self_0 = setmetatable({ }, _base_0)
90 cls.__init(_self_0, ...)
91 return _self_0
87 end 92 end
88 _class_0 = setmetatable({ 93 })
89 __init = function() end, 94 _base_0.__class = _class_0
90 __base = _base_0, 95 local self = _class_0;
91 __name = "A" 96 func(...)
92 }, { 97 A = _class_0
93 __index = _base_0, 98 return _class_0
94 __call = function(cls, ...) 99 end
95 local _self_0 = setmetatable({ }, _base_0) 100end
96 cls.__init(_self_0, ...) 101local _anon_func_8 = function(pairs, tb)
97 return _self_0 102 local _tbl_0 = { }
98 end 103 for k, v in pairs(tb) do
99 }) 104 _tbl_0[k] = v
100 _base_0.__class = _class_0 105 end
101 local self = _class_0; 106 return _tbl_0
102 func(...) 107end
103 A = _class_0 108local _anon_func_9 = function(pairs, tb, ...)
104 return _class_0 109 local _tbl_0 = { }
105 end 110 for k, v in pairs(tb) do
106 end)(...)) 111 _tbl_0[k] = v(...)
107 f_tblcomp((function() 112 end
108 local _tbl_0 = { } 113 return _tbl_0
109 for k, v in pairs(tb) do 114end
110 _tbl_0[k] = v 115local _anon_func_10 = function(items)
111 end 116 local _tbl_0 = { }
112 return _tbl_0 117 for _index_0 = 1, #items do
113 end)()) 118 local item = items[_index_0]
114 f_tblcomp((function(...) 119 _tbl_0[item] = true
115 local _tbl_0 = { } 120 end
116 for k, v in pairs(tb) do 121 return _tbl_0
117 _tbl_0[k] = v(...) 122end
118 end 123local _anon_func_11 = function(items, ...)
119 return _tbl_0 124 local _tbl_0 = { }
120 end)(...)) 125 for _index_0 = 1, #items do
121 f_tblcomp((function() 126 local item = items[_index_0]
122 local _tbl_0 = { } 127 _tbl_0[item(...)] = true
123 local _list_0 = items 128 end
124 for _index_0 = 1, #_list_0 do 129 return _tbl_0
125 local item = _list_0[_index_0] 130end
126 _tbl_0[item] = true 131local _anon_func_12 = function(func)
127 end 132 do
128 return _tbl_0
129 end)())
130 f_tblcomp((function(...)
131 local _tbl_0 = { }
132 local _list_0 = items
133 for _index_0 = 1, #_list_0 do
134 local item = _list_0[_index_0]
135 _tbl_0[item(...)] = true
136 end
137 return _tbl_0
138 end)(...))
139 f_do((function()
140 return func() 133 return func()
141 end)()) 134 end
142 f_do((function(...) 135end
136local _anon_func_13 = function(func, ...)
137 do
143 return func(...) 138 return func(...)
144 end)(...)) 139 end
145 f_while((function() 140end
146 local _accum_0 = { } 141local _anon_func_14 = function(func)
147 local _len_0 = 1 142 local _accum_0 = { }
148 while false do 143 local _len_0 = 1
149 _accum_0[_len_0] = func() 144 while false do
150 _len_0 = _len_0 + 1 145 _accum_0[_len_0] = func()
151 end 146 _len_0 = _len_0 + 1
152 return _accum_0 147 end
153 end)()) 148 return _accum_0
154 f_while((function(...) 149end
155 local _accum_0 = { } 150local _anon_func_15 = function(func, ...)
156 local _len_0 = 1 151 local _accum_0 = { }
157 while false do 152 local _len_0 = 1
158 _accum_0[_len_0] = func(...) 153 while false do
159 _len_0 = _len_0 + 1 154 _accum_0[_len_0] = func(...)
160 end 155 _len_0 = _len_0 + 1
161 return _accum_0 156 end
162 end)(...)) 157 return _accum_0
163 f_if((function() 158end
164 if false then 159local _anon_func_16 = function(func)
165 return func() 160 if false then
166 end 161 return func()
167 end)()) 162 end
168 f_if((function(...) 163end
169 if false then 164local _anon_func_17 = function(func, ...)
170 return func(...) 165 if false then
171 end 166 return func(...)
172 end)(...)) 167 end
173 f_unless((function() 168end
174 if not true then 169local _anon_func_18 = function(func)
175 return func() 170 if not true then
176 end 171 return func()
177 end)()) 172 end
178 f_unless((function(...) 173end
179 if not true then 174local _anon_func_19 = function(func, ...)
180 return func(...) 175 if not true then
181 end 176 return func(...)
182 end)(...)) 177 end
183 f_switch((function() 178end
184 local _exp_0 = x 179local _anon_func_20 = function(x, func)
185 if "abc" == _exp_0 then 180 if "abc" == x then
186 return func() 181 return func()
187 end 182 end
188 end)()) 183end
189 f_switch((function(...) 184local _anon_func_21 = function(x, func, ...)
190 local _exp_0 = x 185 if "abc" == x then
191 if "abc" == _exp_0 then 186 return func(...)
192 return func(...) 187 end
193 end 188end
194 end)(...)) 189local _anon_func_22 = function(func)
195 f_eop((function() 190 if func ~= nil then
196 local _obj_0 = func 191 return func()
197 if _obj_0 ~= nil then 192 end
198 return _obj_0() 193 return nil
199 end 194end
200 return nil 195local _anon_func_23 = function(func, ...)
201 end)()) 196 if func ~= nil then
202 f_eop((function(...) 197 return func(...)
203 local _obj_0 = func 198 end
204 if _obj_0 ~= nil then 199 return nil
205 return _obj_0(...) 200end
206 end 201local _anon_func_24 = function(select, print, ...)
207 return nil 202 do
208 end)(...)) 203 print(select("#", ...))
204 return print(...)
205 end
206end
207local _anon_func_25 = function(print, ...)
208 do
209 return print(...)
210 end
211end
212local _anon_func_26 = function(x, tb, tb2)
213 if 1 == x then
214 tb.x = 123
215 return tb
216 else
217 return tb2
218 end
219end
220local _anon_func_27 = function(print, ...)
221 do
222 return print(...)
223 end
224end
225local _anon_func_28 = function(cond)
226 if cond then
227 return 3, 4, 5
228 end
229end
230local _anon_func_29 = function(print, _arg_0, ...)
231 do
232 local tb = _arg_0
233 return print(...)
234 end
235end
236local join
237join = function(...)
238 f_with(_anon_func_0(a))
239 f_with(_anon_func_1(a, ...))
240 f_listcomp(_anon_func_2(items))
241 f_listcomp(_anon_func_3(items, ...))
242 f_listcomp(_anon_func_4(items))
243 f_listcomp(_anon_func_5(items, ...))
244 f_class(_anon_func_6(setmetatable, func))
245 f_class(_anon_func_7(setmetatable, func, ...))
246 f_tblcomp(_anon_func_8(pairs, tb))
247 f_tblcomp(_anon_func_9(pairs, tb, ...))
248 f_tblcomp(_anon_func_10(items))
249 f_tblcomp(_anon_func_11(items, ...))
250 f_do(_anon_func_12(func))
251 f_do(_anon_func_13(func, ...))
252 f_while(_anon_func_14(func))
253 f_while(_anon_func_15(func, ...))
254 f_if(_anon_func_16(func))
255 f_if(_anon_func_17(func, ...))
256 f_unless(_anon_func_18(func))
257 f_unless(_anon_func_19(func, ...))
258 f_switch(_anon_func_20(x, func))
259 f_switch(_anon_func_21(x, func, ...))
260 f_eop(_anon_func_22(func))
261 f_eop(_anon_func_23(func, ...))
209 f_colon((function() 262 f_colon((function()
210 local _base_0 = f() 263 local _base_0 = f()
211 local _fn_0 = _base_0.func 264 local _fn_0 = _base_0.func
@@ -240,40 +293,17 @@ join = function(...)
240 fn_many_args = function() 293 fn_many_args = function()
241 return 10, nil, 20, nil, 30 294 return 10, nil, 20, nil, 30
242 end 295 end
243 return (function(...) 296 return _anon_func_24(select, print, fn_many_args())
244 print(select("#", ...))
245 return print(...)
246 end)(fn_many_args())
247 end)(fn(true)) 297 end)(fn(true))
248 end 298 end
249 do 299 do
250 (function(...) 300 _anon_func_25(print, _anon_func_26(x, tb, tb2))
251 return print(...)
252 end)((function()
253 local _exp_0 = x
254 if 1 == _exp_0 then
255 local _with_0 = tb
256 _with_0.x = 123
257 return _with_0
258 else
259 return tb2
260 end
261 end)())
262 end 301 end
263 do 302 do
264 (function(...) 303 _anon_func_27(print, 1, 2, _anon_func_28(cond))
265 return print(...)
266 end)(1, 2, (function()
267 if cond then
268 return 3, 4, 5
269 end
270 end)())
271 end 304 end
272 do 305 do
273 (function(_arg_0, ...) 306 _anon_func_29(print, {
274 local tb = _arg_0
275 return print(...)
276 end)({
277 name = "abc", 307 name = "abc",
278 value = 123 308 value = 123
279 }) 309 })
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp
index fbf7a63..3a22345 100644
--- a/src/yuescript/yue_ast.cpp
+++ b/src/yuescript/yue_ast.cpp
@@ -195,7 +195,7 @@ std::string YueLineComment_t::to_string(void* ud) const {
195} 195}
196std::string MultilineCommentInner_t::to_string(void* ud) const { 196std::string MultilineCommentInner_t::to_string(void* ud) const {
197 auto info = reinterpret_cast<YueFormat*>(ud); 197 auto info = reinterpret_cast<YueFormat*>(ud);
198 return "--[["s + info->convert(this) + "]]"s; 198 return info->convert(this);
199} 199}
200std::string Variable_t::to_string(void* ud) const { 200std::string Variable_t::to_string(void* ud) const {
201 return name->to_string(ud); 201 return name->to_string(ud);
@@ -583,12 +583,12 @@ std::string CatchBlock_t::to_string(void* ud) const {
583 auto info = reinterpret_cast<YueFormat*>(ud); 583 auto info = reinterpret_cast<YueFormat*>(ud);
584 auto line = "catch "s + err->to_string(ud); 584 auto line = "catch "s + err->to_string(ud);
585 info->pushScope(); 585 info->pushScope();
586 auto block = body->to_string(ud); 586 auto blockStr = block->to_string(ud);
587 if (block.empty()) { 587 if (blockStr.empty()) {
588 block = info->ind() + "--"s; 588 blockStr = info->ind() + "--"s;
589 } 589 }
590 info->popScope(); 590 info->popScope();
591 return line + '\n' + block; 591 return line + '\n' + blockStr;
592} 592}
593std::string Try_t::to_string(void* ud) const { 593std::string Try_t::to_string(void* ud) const {
594 auto info = reinterpret_cast<YueFormat*>(ud); 594 auto info = reinterpret_cast<YueFormat*>(ud);
@@ -609,21 +609,158 @@ std::string Try_t::to_string(void* ud) const {
609 } 609 }
610 return join(temp, "\n"sv); 610 return join(temp, "\n"sv);
611} 611}
612std::string Comprehension_t::to_string(void* ud) const { 612static bool isInBlockExp(ast_node* node, bool last = false) {
613 str_list temp; 613 if (auto exp = ast_cast<Exp_t>(node)) {
614 for (const auto& item : items.objects()) { 614 UnaryExp_t* unaryExp = nullptr;
615 temp.push_back(item->to_string(ud)); 615 if (exp->opValues.empty()) {
616 } 616 unaryExp = static_cast<UnaryExp_t*>(exp->pipeExprs.back());
617 if (temp.size() > 0) { 617 } else {
618 temp.front().insert(0, temp.front()[0] == '[' ? " "s : ""s); 618 unaryExp = static_cast<UnaryExp_t*>(static_cast<ExpOpValue_t*>(exp->opValues.back())->pipeExprs.back());
619 }
620 auto value = static_cast<Value_t*>(unaryExp->expos.back());
621 if (auto simpleValue = value->item.as<SimpleValue_t>()) {
622 switch (simpleValue->value->get_id()) {
623 case id<TableLit_t>():
624 case id<ConstValue_t>():
625 case id<Num_t>():
626 case id<VarArg_t>():
627 case id<TblComprehension_t>():
628 case id<Comprehension_t>():
629 return false;
630 case id<FunLit_t>():
631 if (!last) {
632 return true;
633 }
634 return false;
635 default:
636 return true;
637 }
638 } else if (auto chainValue = value->item.as<ChainValue_t>()) {
639 if (ast_is<InvokeArgs_t>(chainValue->items.back())) {
640 return true;
641 }
642 } else if (!last && value->item.is<SimpleTable_t>()) {
643 return true;
644 }
645 } else if (ast_is<TableBlock_t>(node)) {
646 return true;
647 } else {
648 switch (node->get_id()) {
649 case id<VariablePairDef_t>(): {
650 auto pair = static_cast<VariablePairDef_t*>(node);
651 if (pair->defVal) {
652 return true;
653 }
654 return false;
655 }
656 case id<NormalPairDef_t>(): {
657 auto pair = static_cast<NormalPairDef_t*>(node);
658 if (pair->defVal) {
659 return true;
660 }
661 return isInBlockExp(pair->pair->value);
662 }
663 case id<SpreadExp_t>(): {
664 auto pair = static_cast<SpreadExp_t*>(node);
665 return isInBlockExp(pair->exp);
666 }
667 case id<NormalDef_t>(): {
668 auto pair = static_cast<NormalDef_t*>(node);
669 if (pair->defVal) {
670 return true;
671 }
672 return isInBlockExp(pair->item);
673 }
674 case id<MetaVariablePairDef_t>(): {
675 auto pair = static_cast<MetaVariablePairDef_t*>(node);
676 if (pair->defVal) {
677 return true;
678 }
679 return false;
680 }
681 case id<MetaNormalPairDef_t>(): {
682 auto pair = static_cast<MetaNormalPairDef_t*>(node);
683 if (pair->defVal) {
684 return true;
685 }
686 return isInBlockExp(pair->pair->value);
687 }
688 case id<VariablePair_t>(): {
689 return false;
690 }
691 case id<NormalPair_t>(): {
692 auto pair = static_cast<NormalPair_t*>(node);
693 return isInBlockExp(pair->value);
694 }
695 case id<MetaVariablePair_t>(): {
696 return false;
697 }
698 case id<MetaNormalPair_t>(): {
699 auto pair = static_cast<MetaNormalPair_t*>(node);
700 return isInBlockExp(pair->value);
701 }
702 case id<TableBlockIndent_t>(): {
703 return true;
704 }
705 case id<SpreadListExp_t>(): {
706 auto pair = static_cast<SpreadListExp_t*>(node);
707 return isInBlockExp(pair->exp);
708 }
709 default:
710 return false;
711 }
619 } 712 }
713 return false;
714}
715std::string Comprehension_t::to_string(void* ud) const {
620 if (items.size() != 2 || !ast_is<CompInner_t>(items.back())) { 716 if (items.size() != 2 || !ast_is<CompInner_t>(items.back())) {
621 if (items.size() == 1) { 717 if (items.size() == 1) {
718 str_list temp;
719 for (const auto& item : items.objects()) {
720 temp.push_back(item->to_string(ud));
721 }
722 if (temp.size() > 0) {
723 temp.front().insert(0, temp.front()[0] == '[' ? " "s : ""s);
724 }
622 return '[' + join(temp, ", "sv) + ",]"s; 725 return '[' + join(temp, ", "sv) + ",]"s;
623 } else { 726 } else {
624 return '[' + join(temp, ", "sv) + ']'; 727 bool hasInBlockExp = false;
728 for (auto value : items.objects()) {
729 if (isInBlockExp(value, value == items.back())) {
730 hasInBlockExp = true;
731 break;
732 }
733 }
734 if (hasInBlockExp) {
735 auto info = reinterpret_cast<YueFormat*>(ud);
736 str_list temp;
737 temp.emplace_back("["s);
738 info->pushScope();
739 for (auto value : items.objects()) {
740 temp.emplace_back(info->ind() + value->to_string(ud));
741 }
742 info->popScope();
743 temp.emplace_back(info->ind() + ']');
744 return join(temp, "\n"sv);
745 } else {
746 str_list temp;
747 for (const auto& item : items.objects()) {
748 temp.push_back(item->to_string(ud));
749 }
750 if (temp.size() > 0) {
751 temp.front().insert(0, temp.front()[0] == '[' ? " "s : ""s);
752 }
753 return '[' + join(temp, ", "sv) + ']';
754 }
625 } 755 }
626 } else { 756 } else {
757 str_list temp;
758 for (const auto& item : items.objects()) {
759 temp.push_back(item->to_string(ud));
760 }
761 if (temp.size() > 0) {
762 temp.front().insert(0, temp.front()[0] == '[' ? " "s : ""s);
763 }
627 return '[' + join(temp, " "sv) + ']'; 764 return '[' + join(temp, " "sv) + ']';
628 } 765 }
629} 766}
@@ -834,109 +971,6 @@ std::string Slice_t::to_string(void* ud) const {
834 auto valueStr = join(temp); 971 auto valueStr = join(temp);
835 return '[' + (valueStr[0] == '[' ? " "s : ""s) + valueStr + ']'; 972 return '[' + (valueStr[0] == '[' ? " "s : ""s) + valueStr + ']';
836} 973}
837static bool isInBlockExp(ast_node* node, bool last = false) {
838 if (auto exp = ast_cast<Exp_t>(node)) {
839 UnaryExp_t* unaryExp = nullptr;
840 if (exp->opValues.empty()) {
841 unaryExp = static_cast<UnaryExp_t*>(exp->pipeExprs.back());
842 } else {
843 unaryExp = static_cast<UnaryExp_t*>(static_cast<ExpOpValue_t*>(exp->opValues.back())->pipeExprs.back());
844 }
845 auto value = static_cast<Value_t*>(unaryExp->expos.back());
846 if (auto simpleValue = value->item.as<SimpleValue_t>()) {
847 switch (simpleValue->value->get_id()) {
848 case id<TableLit_t>():
849 case id<ConstValue_t>():
850 case id<Num_t>():
851 case id<VarArg_t>():
852 case id<TblComprehension_t>():
853 case id<Comprehension_t>():
854 return false;
855 case id<FunLit_t>():
856 if (!last) {
857 return true;
858 }
859 return false;
860 default:
861 return true;
862 }
863 } else if (auto chainValue = value->item.as<ChainValue_t>()) {
864 if (ast_is<InvokeArgs_t>(chainValue->items.back())) {
865 return true;
866 }
867 } else if (!last && value->item.is<SimpleTable_t>()) {
868 return true;
869 }
870 } else if (ast_is<TableBlock_t>(node)) {
871 return true;
872 } else {
873 switch (node->get_id()) {
874 case id<VariablePairDef_t>(): {
875 auto pair = static_cast<VariablePairDef_t*>(node);
876 if (pair->defVal) {
877 return true;
878 }
879 return false;
880 }
881 case id<NormalPairDef_t>(): {
882 auto pair = static_cast<NormalPairDef_t*>(node);
883 if (pair->defVal) {
884 return true;
885 }
886 return isInBlockExp(pair->pair->value);
887 }
888 case id<SpreadExp_t>(): {
889 auto pair = static_cast<SpreadExp_t*>(node);
890 return isInBlockExp(pair->exp);
891 }
892 case id<NormalDef_t>(): {
893 auto pair = static_cast<NormalDef_t*>(node);
894 if (pair->defVal) {
895 return true;
896 }
897 return isInBlockExp(pair->item);
898 }
899 case id<MetaVariablePairDef_t>(): {
900 auto pair = static_cast<MetaVariablePairDef_t*>(node);
901 if (pair->defVal) {
902 return true;
903 }
904 return false;
905 }
906 case id<MetaNormalPairDef_t>(): {
907 auto pair = static_cast<MetaNormalPairDef_t*>(node);
908 if (pair->defVal) {
909 return true;
910 }
911 return isInBlockExp(pair->pair->value);
912 }
913 case id<VariablePair_t>(): {
914 return false;
915 }
916 case id<NormalPair_t>(): {
917 auto pair = static_cast<NormalPair_t*>(node);
918 return isInBlockExp(pair->value);
919 }
920 case id<MetaVariablePair_t>(): {
921 return false;
922 }
923 case id<MetaNormalPair_t>(): {
924 auto pair = static_cast<MetaNormalPair_t*>(node);
925 return isInBlockExp(pair->value);
926 }
927 case id<TableBlockIndent_t>(): {
928 return true;
929 }
930 case id<SpreadListExp_t>(): {
931 auto pair = static_cast<SpreadListExp_t*>(node);
932 return isInBlockExp(pair->exp);
933 }
934 default:
935 return false;
936 }
937 }
938 return false;
939}
940std::string Invoke_t::to_string(void* ud) const { 974std::string Invoke_t::to_string(void* ud) const {
941 if (args.empty()) { 975 if (args.empty()) {
942 return "!"s; 976 return "!"s;
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 73ffc9a..2ea0a85 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -368,8 +368,8 @@ AST_END(Do, "do"sv)
368 368
369AST_NODE(CatchBlock) 369AST_NODE(CatchBlock)
370 ast_ptr<true, Variable_t> err; 370 ast_ptr<true, Variable_t> err;
371 ast_ptr<true, Block_t> body; 371 ast_ptr<true, Block_t> block;
372 AST_MEMBER(CatchBlock, &err, &body) 372 AST_MEMBER(CatchBlock, &err, &block)
373AST_END(CatchBlock, "catch_block"sv) 373AST_END(CatchBlock, "catch_block"sv)
374 374
375AST_NODE(Try) 375AST_NODE(Try)
@@ -759,6 +759,7 @@ AST_NODE(FunLit)
759 ast_sel<false, ExpListLow_t, DefaultValue_t> defaultReturn; 759 ast_sel<false, ExpListLow_t, DefaultValue_t> defaultReturn;
760 ast_ptr<true, FnArrow_t> arrow; 760 ast_ptr<true, FnArrow_t> arrow;
761 ast_ptr<false, Body_t> body; 761 ast_ptr<false, Body_t> body;
762 bool noRecursion = false;
762 AST_MEMBER(FunLit, &argsDef, &defaultReturn, &arrow, &body) 763 AST_MEMBER(FunLit, &argsDef, &defaultReturn, &arrow, &body)
763AST_END(FunLit, "fun_lit"sv) 764AST_END(FunLit, "fun_lit"sv)
764 765
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index c991733..d416dbd 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.22.3"sv; 78const std::string_view version = "0.23.0"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 {
@@ -95,13 +95,15 @@ CompileInfo::CompileInfo(
95 std::unique_ptr<GlobalVars>&& globals, 95 std::unique_ptr<GlobalVars>&& globals,
96 std::unique_ptr<Options>&& options, 96 std::unique_ptr<Options>&& options,
97 double parseTime, 97 double parseTime,
98 double compileTime) 98 double compileTime,
99 bool usedVar)
99 : codes(std::move(codes)) 100 : codes(std::move(codes))
100 , error(std::move(error)) 101 , error(std::move(error))
101 , globals(std::move(globals)) 102 , globals(std::move(globals))
102 , options(std::move(options)) 103 , options(std::move(options))
103 , parseTime(parseTime) 104 , parseTime(parseTime)
104 , compileTime(compileTime) { } 105 , compileTime(compileTime)
106 , usedVar(usedVar) { }
105 107
106CompileInfo::CompileInfo(CompileInfo&& other) 108CompileInfo::CompileInfo(CompileInfo&& other)
107 : codes(std::move(other.codes)) 109 : codes(std::move(other.codes))
@@ -214,7 +216,8 @@ public:
214 } 216 }
215 str_list out; 217 str_list out;
216 pushScope(); 218 pushScope();
217 _enableReturn.push(_info.moduleName.empty()); 219 _funcStates.push({false, _info.moduleName.empty()});
220 _funcLevel = 1;
218 _gotoScopes.push(0); 221 _gotoScopes.push(0);
219 _gotoScope = 1; 222 _gotoScope = 1;
220 _varArgs.push({true, false}); 223 _varArgs.push({true, false});
@@ -252,9 +255,8 @@ public:
252 if (config.lintGlobalVariable) { 255 if (config.lintGlobalVariable) {
253 globals = std::make_unique<GlobalVars>(); 256 globals = std::make_unique<GlobalVars>();
254 for (const auto& var : _globals) { 257 for (const auto& var : _globals) {
255 int line, col; 258 auto [name, line, col, accessType] = var.second;
256 std::tie(line, col) = var.second; 259 globals->push_back({name, line + _config.lineOffset, col, accessType});
257 globals->push_back({var.first, line + _config.lineOffset, col});
258 } 260 }
259 std::sort(globals->begin(), globals->end(), [](const GlobalVar& varA, const GlobalVar& varB) { 261 std::sort(globals->begin(), globals->end(), [](const GlobalVar& varA, const GlobalVar& varB) {
260 if (varA.line < varB.line) { 262 if (varA.line < varB.line) {
@@ -286,7 +288,8 @@ public:
286 } 288 }
287 } 289 }
288#endif // YUE_NO_MACRO 290#endif // YUE_NO_MACRO
289 return {std::move(out.back()), std::nullopt, std::move(globals), std::move(options), parseTime, compileTime}; 291 bool usedVar = _varArgs.top().usedVar;
292 return {std::move(out.back()), std::nullopt, std::move(globals), std::move(options), parseTime, compileTime, usedVar};
290 } catch (const CompileError& error) { 293 } catch (const CompileError& error) {
291 auto displayMessage = _info.errorMessage(error.what(), error.line, error.col, _config.lineOffset); 294 auto displayMessage = _info.errorMessage(error.what(), error.line, error.col, _config.lineOffset);
292 return { 295 return {
@@ -298,7 +301,7 @@ public:
298 displayMessage}, 301 displayMessage},
299 std::move(globals), 302 std::move(globals),
300 std::move(options), 303 std::move(options),
301 parseTime, compileTime}; 304 parseTime, compileTime, false};
302 } 305 }
303 } else { 306 } else {
304 const auto& error = _info.error.value(); 307 const auto& error = _info.error.value();
@@ -312,7 +315,7 @@ public:
312 ""}, 315 ""},
313 std::move(globals), 316 std::move(globals),
314 std::move(options), 317 std::move(options),
315 parseTime, compileTime}; 318 parseTime, compileTime, false};
316 } 319 }
317 auto displayMessage = _info.errorMessage(error.msg, error.line, error.col, _config.lineOffset); 320 auto displayMessage = _info.errorMessage(error.msg, error.line, error.col, _config.lineOffset);
318 return { 321 return {
@@ -324,7 +327,7 @@ public:
324 displayMessage}, 327 displayMessage},
325 std::move(globals), 328 std::move(globals),
326 std::move(options), 329 std::move(options),
327 parseTime, compileTime}; 330 parseTime, compileTime, false};
328 } 331 }
329 } 332 }
330 333
@@ -341,7 +344,7 @@ public:
341 _varArgs = {}; 344 _varArgs = {};
342 _withVars = {}; 345 _withVars = {};
343 _continueVars = {}; 346 _continueVars = {};
344 _enableReturn = {}; 347 _funcStates = {};
345#ifndef YUE_NO_MACRO 348#ifndef YUE_NO_MACRO
346 if (_useModule) { 349 if (_useModule) {
347 _useModule = false; 350 _useModule = false;
@@ -375,16 +378,22 @@ private:
375 bool usedVar; 378 bool usedVar;
376 }; 379 };
377 std::stack<VarArgState> _varArgs; 380 std::stack<VarArgState> _varArgs;
378 std::stack<bool> _enableReturn; 381 struct FuncState {
382 bool isAnon;
383 bool enableReturn;
384 };
385 int _funcLevel = 0;
386 std::stack<FuncState> _funcStates;
379 std::stack<bool> _enableBreakLoop; 387 std::stack<bool> _enableBreakLoop;
380 std::stack<std::string> _withVars; 388 std::stack<std::string> _withVars;
389 str_list _rootDefs;
381 struct ContinueVar { 390 struct ContinueVar {
382 std::string var; 391 std::string var;
383 ast_ptr<false, ExpListAssign_t> condAssign; 392 ast_ptr<false, ExpListAssign_t> condAssign;
384 }; 393 };
385 std::stack<ContinueVar> _continueVars; 394 std::stack<ContinueVar> _continueVars;
386 std::list<std::unique_ptr<input>> _codeCache; 395 std::list<std::unique_ptr<input>> _codeCache;
387 std::unordered_map<std::string, std::pair<int, int>> _globals; 396 std::unordered_map<std::string, std::tuple<std::string, int, int, AccessType>> _globals;
388 std::ostringstream _buf; 397 std::ostringstream _buf;
389 std::ostringstream _joinBuf; 398 std::ostringstream _joinBuf;
390 const std::string _newLine = "\n"; 399 const std::string _newLine = "\n";
@@ -526,7 +535,7 @@ private:
526 return local; 535 return local;
527 } 536 }
528 537
529 bool isGlobal(const std::string& name) const { 538 bool isDeclaredAsGlobal(const std::string& name) const {
530 bool global = false; 539 bool global = false;
531 for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { 540 for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) {
532 auto vars = it->vars.get(); 541 auto vars = it->vars.get();
@@ -1020,7 +1029,7 @@ private:
1020 return type; 1029 return type;
1021 } 1030 }
1022 1031
1023 std::string singleVariableFrom(ChainValue_t* chainValue) { 1032 std::string singleVariableFrom(ChainValue_t* chainValue, AccessType accessType) {
1024 BLOCK_START 1033 BLOCK_START
1025 BREAK_IF(!chainValue); 1034 BREAK_IF(!chainValue);
1026 BREAK_IF(chainValue->items.size() != 1); 1035 BREAK_IF(chainValue->items.size() != 1);
@@ -1034,7 +1043,7 @@ private:
1034 } 1043 }
1035 BREAK_IF(!var); 1044 BREAK_IF(!var);
1036 str_list tmp; 1045 str_list tmp;
1037 transformCallable(callable, tmp); 1046 transformCallable(callable, tmp, accessType);
1038 return tmp.back(); 1047 return tmp.back();
1039 BLOCK_END 1048 BLOCK_END
1040 return Empty; 1049 return Empty;
@@ -1064,7 +1073,7 @@ private:
1064 } 1073 }
1065 } 1074 }
1066 1075
1067 std::string singleVariableFrom(ast_node* expList, bool accessing) { 1076 std::string singleVariableFrom(ast_node* expList, AccessType accessType) {
1068 if (!ast_is<Exp_t, ExpList_t, Value_t>(expList)) return Empty; 1077 if (!ast_is<Exp_t, ExpList_t, Value_t>(expList)) return Empty;
1069 BLOCK_START 1078 BLOCK_START
1070 auto value = ast_cast<Value_t>(expList); 1079 auto value = ast_cast<Value_t>(expList);
@@ -1078,14 +1087,7 @@ private:
1078 auto callable = ast_cast<Callable_t>(chainValue->items.front()); 1087 auto callable = ast_cast<Callable_t>(chainValue->items.front());
1079 BREAK_IF(!callable || !(callable->item.is<Variable_t>() || callable->get_by_path<SelfItem_t, Self_t>())); 1088 BREAK_IF(!callable || !(callable->item.is<Variable_t>() || callable->get_by_path<SelfItem_t, Self_t>()));
1080 str_list tmp; 1089 str_list tmp;
1081 if (accessing) { 1090 transformCallable(callable, tmp, accessType);
1082 transformCallable(callable, tmp);
1083 } else {
1084 bool lintGlobal = _config.lintGlobalVariable;
1085 _config.lintGlobalVariable = false;
1086 transformCallable(callable, tmp);
1087 _config.lintGlobalVariable = lintGlobal;
1088 }
1089 return tmp.back(); 1091 return tmp.back();
1090 BLOCK_END 1092 BLOCK_END
1091 return Empty; 1093 return Empty;
@@ -1235,7 +1237,7 @@ private:
1235 return unary; 1237 return unary;
1236 } 1238 }
1237 auto value = static_cast<Value_t*>(unary->expos.back()); 1239 auto value = static_cast<Value_t*>(unary->expos.back());
1238 auto varName = singleVariableFrom(value, false); 1240 auto varName = singleVariableFrom(value, AccessType::None);
1239 if (varName.empty() || !isLocal(varName)) { 1241 if (varName.empty() || !isLocal(varName)) {
1240 return unary; 1242 return unary;
1241 } 1243 }
@@ -1243,15 +1245,26 @@ private:
1243 return nullptr; 1245 return nullptr;
1244 } 1246 }
1245 1247
1246 void pushFunctionScope() { 1248 void pushFunctionScope(bool anonFunc) {
1247 _enableReturn.push(true); 1249 _funcLevel += anonFunc ? 0 : 1;
1250 _funcStates.push({anonFunc, true});
1248 _enableBreakLoop.push(false); 1251 _enableBreakLoop.push(false);
1249 _gotoScopes.push(_gotoScope); 1252 _gotoScopes.push(_gotoScope);
1250 _gotoScope++; 1253 _gotoScope++;
1251 } 1254 }
1252 1255
1256
1257 void pushUserFunctionScope() {
1258 pushFunctionScope(false);
1259 }
1260
1261 void pushAnonFunctionScope() {
1262 pushFunctionScope(true);
1263 }
1264
1253 void popFunctionScope() { 1265 void popFunctionScope() {
1254 _enableReturn.pop(); 1266 _funcLevel -= _funcStates.top().isAnon ? 0 : 1;
1267 _funcStates.pop();
1255 _enableBreakLoop.pop(); 1268 _enableBreakLoop.pop();
1256 _gotoScopes.pop(); 1269 _gotoScopes.pop();
1257 } 1270 }
@@ -1276,12 +1289,16 @@ private:
1276 return !_varArgs.empty() && _varArgs.top().usedVar ? "end)(...)"s : "end)()"s; 1289 return !_varArgs.empty() && _varArgs.top().usedVar ? "end)(...)"s : "end)()"s;
1277 } 1290 }
1278 1291
1279 std::string globalVar(std::string_view var, ast_node* x) { 1292 std::string globalVar(std::string_view var, ast_node* x, AccessType accessType) {
1280 std::string str(var); 1293 std::string str(var);
1281 if (_config.lintGlobalVariable) { 1294 if (_config.lintGlobalVariable) {
1282 if (!isDefined(str)) { 1295 if (!isLocal(str)) {
1283 if (_globals.find(str) == _globals.end()) { 1296 auto key = str + ':' + std::to_string(x->m_begin.m_line) + ':' + std::to_string(x->m_begin.m_col);
1284 _globals[str] = {x->m_begin.m_line, x->m_begin.m_col}; 1297 if (_globals.find(key) == _globals.end()) {
1298 if (accessType == AccessType::Read && _funcLevel > 1) {
1299 accessType = AccessType::Capture;
1300 }
1301 _globals[key] = {str, x->m_begin.m_line, x->m_begin.m_col, accessType};
1285 } 1302 }
1286 } 1303 }
1287 } 1304 }
@@ -1532,7 +1549,15 @@ private:
1532 case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break; 1549 case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break;
1533 case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break; 1550 case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break;
1534 case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break; 1551 case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break;
1535 case id<Comprehension_t>(): transformCompCommon(static_cast<Comprehension_t*>(value), out); break; 1552 case id<Comprehension_t>(): {
1553 auto comp = static_cast<Comprehension_t*>(value);
1554 if (comp->items.size() == 2 && ast_is<CompInner_t>(comp->items.back())) {
1555 transformCompCommon(comp, out);
1556 } else {
1557 specialSingleValue = false;
1558 }
1559 break;
1560 }
1536 default: specialSingleValue = false; break; 1561 default: specialSingleValue = false; break;
1537 } 1562 }
1538 if (specialSingleValue) { 1563 if (specialSingleValue) {
@@ -1567,7 +1592,7 @@ private:
1567 _config.lintGlobalVariable = false; 1592 _config.lintGlobalVariable = false;
1568 if (!assignment->action.is<Assign_t>()) return vars; 1593 if (!assignment->action.is<Assign_t>()) return vars;
1569 for (auto exp : assignment->expList->exprs.objects()) { 1594 for (auto exp : assignment->expList->exprs.objects()) {
1570 auto var = singleVariableFrom(exp, true); 1595 auto var = singleVariableFrom(exp, AccessType::Write);
1571 vars.push_back(var.empty() ? Empty : var); 1596 vars.push_back(var.empty() ? Empty : var);
1572 } 1597 }
1573 _config.lintGlobalVariable = lintGlobal; 1598 _config.lintGlobalVariable = lintGlobal;
@@ -1579,7 +1604,7 @@ private:
1579 bool lintGlobal = _config.lintGlobalVariable; 1604 bool lintGlobal = _config.lintGlobalVariable;
1580 _config.lintGlobalVariable = false; 1605 _config.lintGlobalVariable = false;
1581 for (auto exp : with->valueList->exprs.objects()) { 1606 for (auto exp : with->valueList->exprs.objects()) {
1582 auto var = singleVariableFrom(exp, true); 1607 auto var = singleVariableFrom(exp, AccessType::Write);
1583 vars.push_back(var.empty() ? Empty : var); 1608 vars.push_back(var.empty() ? Empty : var);
1584 } 1609 }
1585 _config.lintGlobalVariable = lintGlobal; 1610 _config.lintGlobalVariable = lintGlobal;
@@ -1867,7 +1892,7 @@ private:
1867 throw CompileError("right value missing"sv, values.front()); 1892 throw CompileError("right value missing"sv, values.front());
1868 } 1893 }
1869 transformAssignItem(*vit, args); 1894 transformAssignItem(*vit, args);
1870 _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x); 1895 _buf << indent() << globalVar("setmetatable"sv, x, AccessType::Read) << '(' << join(args, ", "sv) << ')' << nll(x);
1871 temp.push_back(clearBuf()); 1896 temp.push_back(clearBuf());
1872 } else if (ast_is<TableAppendingOp_t>(chainValue->items.back())) { 1897 } else if (ast_is<TableAppendingOp_t>(chainValue->items.back())) {
1873 auto tmpChain = chainValue->new_ptr<ChainValue_t>(); 1898 auto tmpChain = chainValue->new_ptr<ChainValue_t>();
@@ -1880,7 +1905,7 @@ private:
1880 tmpChain->items.push_back(toAst<Callable_t>(_withVars.top(), chainValue)); 1905 tmpChain->items.push_back(toAst<Callable_t>(_withVars.top(), chainValue));
1881 } 1906 }
1882 } 1907 }
1883 auto varName = singleVariableFrom(tmpChain); 1908 auto varName = singleVariableFrom(tmpChain, AccessType::Write);
1884 bool isScoped = false; 1909 bool isScoped = false;
1885 if (varName.empty() || !isLocal(varName)) { 1910 if (varName.empty() || !isLocal(varName)) {
1886 isScoped = true; 1911 isScoped = true;
@@ -2433,7 +2458,7 @@ private:
2433 } 2458 }
2434 } else { 2459 } else {
2435 auto exp = static_cast<Exp_t*>(pair); 2460 auto exp = static_cast<Exp_t*>(pair);
2436 auto varName = singleVariableFrom(exp, false); 2461 auto varName = singleVariableFrom(exp, AccessType::None);
2437 if (varName == "_"sv) break; 2462 if (varName == "_"sv) break;
2438 auto chain = exp->new_ptr<ChainValue_t>(); 2463 auto chain = exp->new_ptr<ChainValue_t>();
2439 auto indexItem = toAst<Exp_t>(std::to_string(index), exp); 2464 auto indexItem = toAst<Exp_t>(std::to_string(index), exp);
@@ -2514,7 +2539,7 @@ private:
2514 } else { 2539 } else {
2515 auto chain = exp->new_ptr<ChainValue_t>(); 2540 auto chain = exp->new_ptr<ChainValue_t>();
2516 if (keyIndex) chain->items.push_back(keyIndex); 2541 if (keyIndex) chain->items.push_back(keyIndex);
2517 auto varName = singleVariableFrom(exp, false); 2542 auto varName = singleVariableFrom(exp, AccessType::None);
2518 pairs.push_back({exp, 2543 pairs.push_back({exp,
2519 varName, 2544 varName,
2520 chain, 2545 chain,
@@ -2801,7 +2826,7 @@ private:
2801 } 2826 }
2802 valueItems.push_back(*j); 2827 valueItems.push_back(*j);
2803 if (!varDefOnly && !subDestruct->values.empty() && !subMetaDestruct->values.empty()) { 2828 if (!varDefOnly && !subDestruct->values.empty() && !subMetaDestruct->values.empty()) {
2804 auto var = singleVariableFrom(*j, false); 2829 auto var = singleVariableFrom(*j, AccessType::None);
2805 if (var.empty() || !isLocal(var)) { 2830 if (var.empty() || !isLocal(var)) {
2806 auto objVar = getUnusedName("_obj_"sv); 2831 auto objVar = getUnusedName("_obj_"sv);
2807 addToScope(objVar); 2832 addToScope(objVar);
@@ -2818,7 +2843,7 @@ private:
2818 auto& destruct = destructs.emplace_back(); 2843 auto& destruct = destructs.emplace_back();
2819 if (!varDefOnly) { 2844 if (!varDefOnly) {
2820 destruct.value = valueItems.back(); 2845 destruct.value = valueItems.back();
2821 destruct.valueVar = singleVariableFrom(destruct.value, false); 2846 destruct.valueVar = singleVariableFrom(destruct.value, AccessType::None);
2822 } 2847 }
2823 auto simpleValue = tab->new_ptr<SimpleValue_t>(); 2848 auto simpleValue = tab->new_ptr<SimpleValue_t>();
2824 simpleValue->value.set(tab); 2849 simpleValue->value.set(tab);
@@ -2893,7 +2918,7 @@ private:
2893 } 2918 }
2894 } 2919 }
2895 if (auto value = singleValueFrom(exp); !value || !value->item.is<String_t>()) { 2920 if (auto value = singleValueFrom(exp); !value || !value->item.is<String_t>()) {
2896 auto var = singleVariableFrom(exp, false); 2921 auto var = singleVariableFrom(exp, AccessType::None);
2897 if (var.empty()) { 2922 if (var.empty()) {
2898 if (!des.inlineAssignment) { 2923 if (!des.inlineAssignment) {
2899 des.inlineAssignment = x->new_ptr<ExpListAssign_t>(); 2924 des.inlineAssignment = x->new_ptr<ExpListAssign_t>();
@@ -2986,7 +3011,7 @@ private:
2986 BLOCK_START 3011 BLOCK_START
2987 auto exp = ast_cast<Exp_t>(item); 3012 auto exp = ast_cast<Exp_t>(item);
2988 BREAK_IF(!exp); 3013 BREAK_IF(!exp);
2989 auto var = singleVariableFrom(exp, true); 3014 auto var = singleVariableFrom(exp, AccessType::Write);
2990 BREAK_IF(!var.empty()); 3015 BREAK_IF(!var.empty());
2991 auto upVar = getUnusedName("_update_"sv); 3016 auto upVar = getUnusedName("_update_"sv);
2992 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 3017 auto newAssignment = x->new_ptr<ExpListAssign_t>();
@@ -3038,23 +3063,40 @@ private:
3038 auto assign = static_cast<Assign_t*>(action); 3063 auto assign = static_cast<Assign_t*>(action);
3039 auto defs = transformAssignDefs(expList, DefOp::Check); 3064 auto defs = transformAssignDefs(expList, DefOp::Check);
3040 bool oneLined = defs.size() == expList->exprs.objects().size(); 3065 bool oneLined = defs.size() == expList->exprs.objects().size();
3066 bool nonRecursionFunLit = false;
3041 for (auto val : assign->values.objects()) { 3067 for (auto val : assign->values.objects()) {
3042 if (auto value = singleValueFrom(val)) { 3068 if (auto value = singleValueFrom(val)) {
3043 if (auto spValue = value->item.as<SimpleValue_t>()) { 3069 if (auto spValue = value->item.as<SimpleValue_t>()) {
3044 if (spValue->value.is<FunLit_t>()) { 3070 if (auto funLit = spValue->value.as<FunLit_t>()) {
3045 oneLined = false; 3071 if (funLit->noRecursion) {
3072 nonRecursionFunLit = true;
3073 } else {
3074 oneLined = false;
3075 }
3046 break; 3076 break;
3047 } 3077 }
3048 } 3078 }
3049 } 3079 }
3050 } 3080 }
3051 if (oneLined) { 3081 if (oneLined) {
3052 for (auto value : assign->values.objects()) {
3053 transformAssignItem(value, temp);
3054 }
3055 std::string preDefine = toLocalDecl(defs); 3082 std::string preDefine = toLocalDecl(defs);
3056 for (const auto& def : defs) { 3083 if (nonRecursionFunLit) {
3057 addToScope(def.first); 3084 for (const auto& def : defs) {
3085 addToScope(def.first);
3086 }
3087 for (auto value : assign->values.objects()) {
3088 transformAssignItem(value, temp);
3089 }
3090 } else {
3091 for (auto value : assign->values.objects()) {
3092 transformAssignItem(value, temp);
3093 }
3094 for (const auto& def : defs) {
3095 addToScope(def.first);
3096 }
3097 }
3098 for (ast_node* exp : expList->exprs.objects()) {
3099 singleVariableFrom(exp, AccessType::Write);
3058 } 3100 }
3059 if (preDefine.empty()) { 3101 if (preDefine.empty()) {
3060 transformExpList(expList, temp); 3102 transformExpList(expList, temp);
@@ -3069,6 +3111,9 @@ private:
3069 for (const auto& def : defs) { 3111 for (const auto& def : defs) {
3070 addToScope(def.first); 3112 addToScope(def.first);
3071 } 3113 }
3114 for (ast_node* exp : expList->exprs.objects()) {
3115 singleVariableFrom(exp, AccessType::Write);
3116 }
3072 transformExpList(expList, temp); 3117 transformExpList(expList, temp);
3073 std::string left = std::move(temp.back()); 3118 std::string left = std::move(temp.back());
3074 temp.pop_back(); 3119 temp.pop_back();
@@ -3122,7 +3167,18 @@ private:
3122 str_list temp; 3167 str_list temp;
3123 std::string* funcStart = nullptr; 3168 std::string* funcStart = nullptr;
3124 if (usage == ExpUsage::Closure) { 3169 if (usage == ExpUsage::Closure) {
3125 pushFunctionScope(); 3170 auto x = nodes.front();
3171 auto newIf = x->new_ptr<If_t>();
3172 newIf->type.set(toAst<IfType_t>(unless ? "unless"sv : "if"sv, x));
3173 for (ast_node* node : nodes) {
3174 newIf->nodes.push_back(node);
3175 }
3176 auto simpleValue = x->new_ptr<SimpleValue_t>();
3177 simpleValue->value.set(newIf);
3178 if (transformAsUpValueFunc(newExp(simpleValue, x), out)) {
3179 return;
3180 }
3181 pushAnonFunctionScope();
3126 pushAnonVarArg(); 3182 pushAnonVarArg();
3127 funcStart = &temp.emplace_back(); 3183 funcStart = &temp.emplace_back();
3128 pushScope(); 3184 pushScope();
@@ -3149,12 +3205,12 @@ private:
3149 if (asmt) { 3205 if (asmt) {
3150 auto exp = firstIfCond->condition.get(); 3206 auto exp = firstIfCond->condition.get();
3151 auto x = exp; 3207 auto x = exp;
3152 auto var = singleVariableFrom(exp, false); 3208 auto var = singleVariableFrom(exp, AccessType::None);
3153 if (var.empty() || isGlobal(var)) { 3209 if (var.empty() || isDeclaredAsGlobal(var)) {
3154 storingValue = true; 3210 storingValue = true;
3155 auto desVar = getUnusedName("_des_"sv); 3211 auto desVar = getUnusedName("_des_"sv);
3156 if (asmt->assign->values.objects().size() == 1) { 3212 if (asmt->assign->values.objects().size() == 1) {
3157 auto var = singleVariableFrom(asmt->assign->values.objects().front(), true); 3213 auto var = singleVariableFrom(asmt->assign->values.objects().front(), AccessType::Read);
3158 if (!var.empty() && isLocal(var)) { 3214 if (!var.empty() && isLocal(var)) {
3159 desVar = var; 3215 desVar = var;
3160 storingValue = false; 3216 storingValue = false;
@@ -3300,7 +3356,7 @@ private:
3300 } 3356 }
3301 bool findPlaceHolder = false; 3357 bool findPlaceHolder = false;
3302 for (auto a : args->objects()) { 3358 for (auto a : args->objects()) {
3303 auto name = singleVariableFrom(a, false); 3359 auto name = singleVariableFrom(a, AccessType::None);
3304 if (name == "_"sv) { 3360 if (name == "_"sv) {
3305 if (!findPlaceHolder) { 3361 if (!findPlaceHolder) {
3306 args->swap(a, arg); 3362 args->swap(a, arg);
@@ -3396,7 +3452,7 @@ private:
3396 if (item.second->size() == 1) { 3452 if (item.second->size() == 1) {
3397 if (auto unary = singleUnaryExpFrom(node)) { 3453 if (auto unary = singleUnaryExpFrom(node)) {
3398 if (auto value = singleValueFrom(unary)) { 3454 if (auto value = singleValueFrom(unary)) {
3399 varName = singleVariableFrom(value, true); 3455 varName = singleVariableFrom(value, AccessType::Read);
3400 } 3456 }
3401 if (varName.empty()) { 3457 if (varName.empty()) {
3402 if (auto sval = static_cast<Value_t*>(unary->expos.front())->item.as<SimpleValue_t>()) { 3458 if (auto sval = static_cast<Value_t*>(unary->expos.front())->item.as<SimpleValue_t>()) {
@@ -3597,7 +3653,137 @@ private:
3597 } 3653 }
3598 } 3654 }
3599 3655
3656 std::optional<std::pair<std::string, str_list>> upValueFuncFrom(Exp_t* exp, str_list* ensureArgList = nullptr) {
3657 if (_funcLevel <= 1) return std::nullopt;
3658 auto result = exp->traverse([&](ast_node* node) {
3659 switch (node->get_id()) {
3660 case id<MacroName_t>():
3661 return traversal::Stop;
3662 }
3663 return traversal::Continue;
3664 });
3665 if (result != traversal::Stop) {
3666 str_list args;
3667 bool upVarsAssignedOrCaptured = false;
3668 bool usedVar = false;
3669 ast_ptr<false, Statement_t> stmt;
3670 {
3671 str_list globals;
3672 for (const auto& scope : _scopes) {
3673 if (scope.vars) {
3674 for (const auto& var : *scope.vars) {
3675 globals.push_back(var.first);
3676 }
3677 }
3678 }
3679 auto returnNode = exp->new_ptr<Return_t>();
3680 auto returnList = exp->new_ptr<ExpListLow_t>();
3681 returnList->exprs.push_back(exp);
3682 returnNode->valueList.set(returnList);
3683 std::string codes;
3684 if (_withVars.empty()) {
3685 codes = YueFormat{}.toString(returnNode);
3686 stmt = exp->new_ptr<Statement_t>();
3687 stmt->content.set(returnNode);
3688 } else {
3689 auto withNode = exp->new_ptr<With_t>();
3690 withNode->valueList.set(toAst<ExpList_t>(_withVars.top(), exp));
3691 auto returnStmt = exp->new_ptr<Statement_t>();
3692 returnStmt->content.set(returnNode);
3693 withNode->body.set(returnStmt);
3694 codes = YueFormat{}.toString(withNode);
3695 stmt = exp->new_ptr<Statement_t>();
3696 auto simpleValue = exp->new_ptr<SimpleValue_t>();
3697 simpleValue->value.set(withNode);
3698 auto newExpr = newExp(simpleValue, exp);
3699 auto explist = exp->new_ptr<ExpList_t>();
3700 explist->exprs.push_back(newExpr);
3701 auto expListAssign = exp->new_ptr<ExpListAssign_t>();
3702 expListAssign->expList.set(explist);
3703 stmt->content.set(expListAssign);
3704 }
3705 if (!globals.empty()) {
3706 codes.insert(0, "global "s + join(globals, ","sv) + '\n');
3707 }
3708 YueConfig config;
3709 config.lintGlobalVariable = true;
3710 auto result = YueCompiler{L, _luaOpen, true}.compile(codes, config);
3711 if (result.error) {
3712 YUEE("failed to compile dues to Yue formatter", exp);
3713 }
3714 usedVar = result.usedVar;
3715 if (result.globals) {
3716 for (const auto& global : *result.globals) {
3717 if (global.accessType != AccessType::Read) {
3718 upVarsAssignedOrCaptured = true;
3719 break;
3720 } else if (std::find(args.begin(), args.end(), global.name) == args.end()) {
3721 args.push_back(global.name);
3722 }
3723 }
3724 }
3725 }
3726 if (!upVarsAssignedOrCaptured) {
3727 auto x = exp;
3728 if (usedVar) {
3729 args.push_back("..."s);
3730 }
3731 if (ensureArgList) {
3732 std::unordered_set<std::string> vars;
3733 for (const auto& arg : args) {
3734 vars.insert(arg);
3735 }
3736 for (const auto& arg : *ensureArgList) {
3737 vars.erase(arg);
3738 }
3739 str_list finalArgs;
3740 for (const auto& arg : vars) {
3741 finalArgs.push_back(arg);
3742 }
3743 for (const auto& arg : *ensureArgList) {
3744 finalArgs.push_back(arg);
3745 }
3746 args = std::move(finalArgs);
3747 }
3748 auto funLit = toAst<FunLit_t>("("s + join(args, ","sv) + ")-> nil"s, x);
3749 funLit->body->content.set(stmt.get());
3750 funLit->noRecursion = true;
3751 auto simpleValue = x->new_ptr<SimpleValue_t>();
3752 simpleValue->value.set(funLit);
3753 auto funcName = getUnusedName("_anon_func_"sv);
3754 auto assignment = assignmentFrom(toAst<Exp_t>(funcName, x), newExp(simpleValue, x), x);
3755 auto scopes = std::move(_scopes);
3756 _scopes.push_back(std::move(scopes.front()));
3757 scopes.pop_front();
3758 int offset = _indentOffset;
3759 _indentOffset = 0;
3760 transformAssignment(assignment, _rootDefs);
3761 scopes.push_front(std::move(_scopes.front()));
3762 _scopes = std::move(scopes);
3763 _indentOffset = offset;
3764 return std::make_pair(funcName, args);
3765 }
3766 }
3767 return std::nullopt;
3768 }
3769
3770 bool transformAsUpValueFunc(Exp_t* exp, str_list& out) {
3771 auto result = upValueFuncFrom(exp);
3772 if (result) {
3773 auto [funcName, args] = std::move(*result);
3774 auto newChainValue = toAst<ChainValue_t>(funcName + '(' + join(args, ","sv) + ')', exp);
3775 transformChainValue(newChainValue, out, ExpUsage::Closure);
3776 return true;
3777 }
3778 return false;
3779 }
3780
3600 void transformNilCoalesedExp(Exp_t* exp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool nilBranchOnly = false) { 3781 void transformNilCoalesedExp(Exp_t* exp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool nilBranchOnly = false) {
3782 if (usage == ExpUsage::Closure) {
3783 if (transformAsUpValueFunc(exp, out)) {
3784 return;
3785 }
3786 }
3601 auto x = exp; 3787 auto x = exp;
3602 str_list temp; 3788 str_list temp;
3603 auto left = exp->new_ptr<Exp_t>(); 3789 auto left = exp->new_ptr<Exp_t>();
@@ -3620,12 +3806,12 @@ private:
3620 } 3806 }
3621 std::string* funcStart = nullptr; 3807 std::string* funcStart = nullptr;
3622 if (usage == ExpUsage::Closure) { 3808 if (usage == ExpUsage::Closure) {
3623 pushFunctionScope(); 3809 pushAnonFunctionScope();
3624 pushAnonVarArg(); 3810 pushAnonVarArg();
3625 funcStart = &temp.emplace_back(); 3811 funcStart = &temp.emplace_back();
3626 pushScope(); 3812 pushScope();
3627 } 3813 }
3628 auto objVar = singleVariableFrom(left, true); 3814 auto objVar = singleVariableFrom(left, AccessType::Read);
3629 auto prepareValue = [&](bool forAssignment = false) { 3815 auto prepareValue = [&](bool forAssignment = false) {
3630 if (objVar.empty() || !isLocal(objVar)) { 3816 if (objVar.empty() || !isLocal(objVar)) {
3631 if (forAssignment) { 3817 if (forAssignment) {
@@ -3724,21 +3910,25 @@ private:
3724 } 3910 }
3725 } 3911 }
3726 3912
3727 void transformCallable(Callable_t* callable, str_list& out, const ast_sel<false, Invoke_t, InvokeArgs_t>& invoke = {}) { 3913 void transformCallable(Callable_t* callable, str_list& out, AccessType accessType, const ast_sel<false, Invoke_t, InvokeArgs_t>& invoke = {}) {
3728 auto item = callable->item.get(); 3914 auto item = callable->item.get();
3729 switch (item->get_id()) { 3915 switch (item->get_id()) {
3730 case id<Variable_t>(): { 3916 case id<Variable_t>(): {
3731 transformVariable(static_cast<Variable_t*>(item), out); 3917 transformVariable(static_cast<Variable_t*>(item), out);
3732 if (_config.lintGlobalVariable && !isLocal(out.back())) { 3918 if (_config.lintGlobalVariable && accessType != AccessType::None && !isLocal(out.back())) {
3733 if (_globals.find(out.back()) == _globals.end()) { 3919 auto key = out.back() + ':' + std::to_string(item->m_begin.m_line) + ':' + std::to_string(item->m_begin.m_col);
3734 _globals[out.back()] = {item->m_begin.m_line, item->m_begin.m_col}; 3920 if (_globals.find(key) == _globals.end()) {
3921 if (accessType == AccessType::Read && _funcLevel > 1) {
3922 accessType = AccessType::Capture;
3923 }
3924 _globals[key] = {out.back(), item->m_begin.m_line, item->m_begin.m_col, accessType};
3735 } 3925 }
3736 } 3926 }
3737 break; 3927 break;
3738 } 3928 }
3739 case id<SelfItem_t>(): { 3929 case id<SelfItem_t>(): {
3740 transformSelfName(static_cast<SelfItem_t*>(item), out, invoke); 3930 transformSelfName(static_cast<SelfItem_t*>(item), out, invoke);
3741 globalVar("self"sv, item); 3931 globalVar("self"sv, item, accessType);
3742 break; 3932 break;
3743 } 3933 }
3744 case id<Parens_t>(): transformParens(static_cast<Parens_t*>(item), out); break; 3934 case id<Parens_t>(): transformParens(static_cast<Parens_t*>(item), out); break;
@@ -3777,7 +3967,7 @@ private:
3777 } 3967 }
3778 3968
3779 void transformFunLit(FunLit_t* funLit, str_list& out) { 3969 void transformFunLit(FunLit_t* funLit, str_list& out) {
3780 pushFunctionScope(); 3970 pushUserFunctionScope();
3781 _varArgs.push({false, false}); 3971 _varArgs.push({false, false});
3782 bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv; 3972 bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv;
3783 pushScope(); 3973 pushScope();
@@ -3951,7 +4141,7 @@ private:
3951 } 4141 }
3952 bool findPlaceHolder = false; 4142 bool findPlaceHolder = false;
3953 for (auto a : args->objects()) { 4143 for (auto a : args->objects()) {
3954 auto name = singleVariableFrom(a, false); 4144 auto name = singleVariableFrom(a, AccessType::None);
3955 if (name == "_"sv) { 4145 if (name == "_"sv) {
3956 if (!findPlaceHolder) { 4146 if (!findPlaceHolder) {
3957 args->swap(a, arg); 4147 args->swap(a, arg);
@@ -4078,6 +4268,26 @@ private:
4078 argNames.push_back("..."s); 4268 argNames.push_back("..."s);
4079 auto newBody = x->new_ptr<Body_t>(); 4269 auto newBody = x->new_ptr<Body_t>();
4080 newBody->content.set(followingBlock); 4270 newBody->content.set(followingBlock);
4271 {
4272 auto doNode = x->new_ptr<Do_t>();
4273 doNode->body.set(newBody);
4274 auto simpleValue = x->new_ptr<SimpleValue_t>();
4275 simpleValue->value.set(doNode);
4276 if (auto result = upValueFuncFrom(newExp(simpleValue, x), &argNames)) {
4277 auto [funcName, args] = std::move(*result);
4278 str_list finalArgs;
4279 for (const auto& arg : args) {
4280 if (std::find(argNames.begin(), argNames.end(), arg) == argNames.end()) {
4281 finalArgs.push_back(arg);
4282 }
4283 }
4284 newBlock->statements.push_back(toAst<Statement_t>(funcName + ' ' + join(finalArgs, ","sv), x));
4285 auto sVal = singleValueFrom(static_cast<Statement_t*>(newBlock->statements.back())->content.to<ExpListAssign_t>()->expList);
4286 ast_to<InvokeArgs_t>(sVal->item.to<ChainValue_t>()->items.back())->args.dup(newInvoke->args);
4287 transformBlock(newBlock, out, usage, assignList, isRoot);
4288 return;
4289 }
4290 }
4081 auto funLit = toAst<FunLit_t>('(' + join(argNames, ","sv) + ")->"s, x); 4291 auto funLit = toAst<FunLit_t>('(' + join(argNames, ","sv) + ")->"s, x);
4082 funLit->body.set(newBody); 4292 funLit->body.set(newBody);
4083 auto newSimpleValue = x->new_ptr<SimpleValue_t>(); 4293 auto newSimpleValue = x->new_ptr<SimpleValue_t>();
@@ -4323,6 +4533,13 @@ private:
4323 str_list temp; 4533 str_list temp;
4324 for (auto node : nodes) { 4534 for (auto node : nodes) {
4325 transformStatement(static_cast<Statement_t*>(node), temp); 4535 transformStatement(static_cast<Statement_t*>(node), temp);
4536 if (isRoot && !_rootDefs.empty()) {
4537 auto last = std::move(temp.back());
4538 temp.pop_back();
4539 temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end());
4540 _rootDefs.clear();
4541 temp.push_back(std::move(last));
4542 }
4326 if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) { 4543 if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) {
4327 auto rit = ++temp.rbegin(); 4544 auto rit = ++temp.rbegin();
4328 if (rit != temp.rend() && !rit->empty()) { 4545 if (rit != temp.rend() && !rit->empty()) {
@@ -4590,7 +4807,7 @@ private:
4590#endif // YUE_NO_MACRO 4807#endif // YUE_NO_MACRO
4591 4808
4592 void transformReturn(Return_t* returnNode, str_list& out) { 4809 void transformReturn(Return_t* returnNode, str_list& out) {
4593 if (!_enableReturn.top()) { 4810 if (!_funcStates.top().enableReturn) {
4594 ast_node* target = returnNode->valueList.get(); 4811 ast_node* target = returnNode->valueList.get();
4595 if (!target) target = returnNode; 4812 if (!target) target = returnNode;
4596 throw CompileError("can not mix use of return and export statements in module scope"sv, target); 4813 throw CompileError("can not mix use of return and export statements in module scope"sv, target);
@@ -4909,7 +5126,14 @@ private:
4909 str_list temp; 5126 str_list temp;
4910 std::string* funcStart = nullptr; 5127 std::string* funcStart = nullptr;
4911 if (usage == ExpUsage::Closure) { 5128 if (usage == ExpUsage::Closure) {
4912 pushFunctionScope(); 5129 auto chainValue = x->new_ptr<ChainValue_t>();
5130 for (ast_node* node : chainList) {
5131 chainValue->items.push_back(node);
5132 }
5133 if (transformAsUpValueFunc(newExp(chainValue, x), out)) {
5134 return true;
5135 }
5136 pushAnonFunctionScope();
4913 pushAnonVarArg(); 5137 pushAnonVarArg();
4914 funcStart = &temp.emplace_back(); 5138 funcStart = &temp.emplace_back();
4915 pushScope(); 5139 pushScope();
@@ -4940,7 +5164,7 @@ private:
4940 break; 5164 break;
4941 } 5165 }
4942 BLOCK_END 5166 BLOCK_END
4943 auto objVar = singleVariableFrom(partOne); 5167 auto objVar = singleVariableFrom(partOne, AccessType::Read);
4944 bool isScoped = false; 5168 bool isScoped = false;
4945 if (objVar.empty() || !isLocal(objVar)) { 5169 if (objVar.empty() || !isLocal(objVar)) {
4946 switch (usage) { 5170 switch (usage) {
@@ -4965,7 +5189,7 @@ private:
4965 } 5189 }
4966 chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), x)); 5190 chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), x));
4967 } 5191 }
4968 auto newObj = singleVariableFrom(chainValue); 5192 auto newObj = singleVariableFrom(chainValue, AccessType::Read);
4969 if (!newObj.empty()) { 5193 if (!newObj.empty()) {
4970 objVar = newObj; 5194 objVar = newObj;
4971 } else { 5195 } else {
@@ -5085,7 +5309,7 @@ private:
5085 pushScope(); 5309 pushScope();
5086 break; 5310 break;
5087 case ExpUsage::Closure: 5311 case ExpUsage::Closure:
5088 pushFunctionScope(); 5312 pushAnonFunctionScope();
5089 pushAnonVarArg(); 5313 pushAnonVarArg();
5090 funcStart = &temp.emplace_back(); 5314 funcStart = &temp.emplace_back();
5091 pushScope(); 5315 pushScope();
@@ -5222,7 +5446,14 @@ private:
5222 str_list temp; 5446 str_list temp;
5223 std::string* funcStart = nullptr; 5447 std::string* funcStart = nullptr;
5224 if (usage == ExpUsage::Closure) { 5448 if (usage == ExpUsage::Closure) {
5225 pushFunctionScope(); 5449 auto chainValue = x->new_ptr<ChainValue_t>();
5450 for (ast_node* node : chainList) {
5451 chainValue->items.push_back(node);
5452 }
5453 if (transformAsUpValueFunc(newExp(chainValue, x), out)) {
5454 return true;
5455 }
5456 pushAnonFunctionScope();
5226 pushAnonVarArg(); 5457 pushAnonVarArg();
5227 funcStart = &temp.emplace_back(); 5458 funcStart = &temp.emplace_back();
5228 pushScope(); 5459 pushScope();
@@ -5349,12 +5580,6 @@ private:
5349 for (auto it = chainList.begin(); it != chainList.end(); ++it) { 5580 for (auto it = chainList.begin(); it != chainList.end(); ++it) {
5350 auto item = *it; 5581 auto item = *it;
5351 switch (item->get_id()) { 5582 switch (item->get_id()) {
5352 case id<Invoke_t>():
5353 transformInvoke(static_cast<Invoke_t*>(item), temp);
5354 break;
5355 case id<DotChainItem_t>():
5356 transformDotChainItem(static_cast<DotChainItem_t*>(item), temp);
5357 break;
5358 case id<ColonChainItem_t>(): { 5583 case id<ColonChainItem_t>(): {
5359 auto colonItem = static_cast<ColonChainItem_t*>(item); 5584 auto colonItem = static_cast<ColonChainItem_t*>(item);
5360 auto current = it; 5585 auto current = it;
@@ -5390,7 +5615,7 @@ private:
5390 chainValue->items.push_back(*i); 5615 chainValue->items.push_back(*i);
5391 } 5616 }
5392 auto exp = newExp(chainValue, x); 5617 auto exp = newExp(chainValue, x);
5393 callVar = singleVariableFrom(exp, true); 5618 callVar = singleVariableFrom(exp, AccessType::Read);
5394 if (callVar.empty() || !isLocal(callVar)) { 5619 if (callVar.empty() || !isLocal(callVar)) {
5395 callVar = getUnusedName("_call_"s); 5620 callVar = getUnusedName("_call_"s);
5396 auto assignment = x->new_ptr<ExpListAssign_t>(); 5621 auto assignment = x->new_ptr<ExpListAssign_t>();
@@ -5413,10 +5638,27 @@ private:
5413 } 5638 }
5414 chainValue->items.push_back(toAst<Exp_t>('\"' + name + '\"', x)); 5639 chainValue->items.push_back(toAst<Exp_t>('\"' + name + '\"', x));
5415 if (auto invoke = ast_cast<Invoke_t>(followItem)) { 5640 if (auto invoke = ast_cast<Invoke_t>(followItem)) {
5416 invoke->args.push_front(toAst<Exp_t>(callVar, x)); 5641 auto newInvoke = x->new_ptr<Invoke_t>();
5642 newInvoke->args.push_back(toAst<Exp_t>(callVar, x));
5643 newInvoke->args.dup(invoke->args);
5644 chainValue->items.push_back(newInvoke);
5645 ++next;
5417 } else { 5646 } else {
5418 auto invokeArgs = static_cast<InvokeArgs_t*>(followItem); 5647 auto invokeArgs = static_cast<InvokeArgs_t*>(followItem);
5419 invokeArgs->args.push_front(toAst<Exp_t>(callVar, x)); 5648 auto newInvokeArgs = x->new_ptr<InvokeArgs_t>();
5649 newInvokeArgs->args.push_back(toAst<Exp_t>(callVar, x));
5650 newInvokeArgs->args.dup(invokeArgs->args);
5651 chainValue->items.push_back(newInvokeArgs);
5652 ++next;
5653 if (next != chainList.end()) {
5654 auto paren = x->new_ptr<Parens_t>();
5655 paren->expr.set(newExp(chainValue, x));
5656 auto ncallable = x->new_ptr<Callable_t>();
5657 ncallable->item.set(paren);
5658 auto nchainValue = x->new_ptr<ChainValue_t>();
5659 nchainValue->items.push_back(ncallable);
5660 chainValue.set(nchainValue);
5661 }
5420 } 5662 }
5421 for (auto i = next; i != chainList.end(); ++i) { 5663 for (auto i = next; i != chainList.end(); ++i) {
5422 chainValue->items.push_back(*i); 5664 chainValue->items.push_back(*i);
@@ -5447,6 +5689,15 @@ private:
5447 } else { 5689 } else {
5448 auto body = x->new_ptr<Body_t>(); 5690 auto body = x->new_ptr<Body_t>();
5449 body->content.set(block); 5691 body->content.set(block);
5692 {
5693 auto doNode = x->new_ptr<Do_t>();
5694 doNode->body.set(body);
5695 auto simpleValue = x->new_ptr<SimpleValue_t>();
5696 simpleValue->value.set(doNode);
5697 if (transformAsUpValueFunc(newExp(simpleValue, x), out)) {
5698 return;
5699 }
5700 }
5450 auto funLit = toAst<FunLit_t>("->"sv, x); 5701 auto funLit = toAst<FunLit_t>("->"sv, x);
5451 funLit->body.set(body); 5702 funLit->body.set(body);
5452 auto simpleValue = x->new_ptr<SimpleValue_t>(); 5703 auto simpleValue = x->new_ptr<SimpleValue_t>();
@@ -5464,9 +5715,21 @@ private:
5464 } 5715 }
5465 return; 5716 return;
5466 } 5717 }
5467 transformColonChainItem(colonItem, temp);
5468 break;
5469 } 5718 }
5719 }
5720 }
5721 for (auto it = chainList.begin(); it != chainList.end(); ++it) {
5722 auto item = *it;
5723 switch (item->get_id()) {
5724 case id<Invoke_t>():
5725 transformInvoke(static_cast<Invoke_t*>(item), temp);
5726 break;
5727 case id<DotChainItem_t>():
5728 transformDotChainItem(static_cast<DotChainItem_t*>(item), temp);
5729 break;
5730 case id<ColonChainItem_t>():
5731 transformColonChainItem(static_cast<ColonChainItem_t*>(item), temp);
5732 break;
5470 case id<Slice_t>(): 5733 case id<Slice_t>():
5471 transformSlice(static_cast<Slice_t*>(item), temp); 5734 transformSlice(static_cast<Slice_t*>(item), temp);
5472 break; 5735 break;
@@ -5478,7 +5741,7 @@ private:
5478 if (ast_is<Invoke_t, InvokeArgs_t>(followItem)) { 5741 if (ast_is<Invoke_t, InvokeArgs_t>(followItem)) {
5479 invoke.set(followItem); 5742 invoke.set(followItem);
5480 } 5743 }
5481 transformCallable(static_cast<Callable_t*>(item), temp, invoke); 5744 transformCallable(static_cast<Callable_t*>(item), temp, AccessType::Read, invoke);
5482 break; 5745 break;
5483 } 5746 }
5484 case id<String_t>(): 5747 case id<String_t>():
@@ -5969,7 +6232,7 @@ private:
5969 std::string varName; 6232 std::string varName;
5970 if (unary_exp->ops.empty() && unary_exp->expos.size() == 1) { 6233 if (unary_exp->ops.empty() && unary_exp->expos.size() == 1) {
5971 auto value = static_cast<Value_t*>(unary_exp->expos.back()); 6234 auto value = static_cast<Value_t*>(unary_exp->expos.back());
5972 varName = singleVariableFrom(value, false); 6235 varName = singleVariableFrom(value, AccessType::None);
5973 if (!isLocal(varName)) { 6236 if (!isLocal(varName)) {
5974 varName.clear(); 6237 varName.clear();
5975 } 6238 }
@@ -6018,7 +6281,7 @@ private:
6018 BLOCK_START 6281 BLOCK_START
6019 BREAK_IF(discrete); 6282 BREAK_IF(discrete);
6020 str_list temp; 6283 str_list temp;
6021 auto checkVar = singleVariableFrom(inExp, false); 6284 auto checkVar = singleVariableFrom(inExp, AccessType::None);
6022 if (usage == ExpUsage::Assignment) { 6285 if (usage == ExpUsage::Assignment) {
6023 auto block = x->new_ptr<Block_t>(); 6286 auto block = x->new_ptr<Block_t>();
6024 if (checkVar.empty() || !isLocal(checkVar)) { 6287 if (checkVar.empty() || !isLocal(checkVar)) {
@@ -6091,7 +6354,11 @@ private:
6091 if (usage == ExpUsage::Return) { 6354 if (usage == ExpUsage::Return) {
6092 arrayCheck(!unary_exp->inExp->not_); 6355 arrayCheck(!unary_exp->inExp->not_);
6093 } else { 6356 } else {
6094 pushFunctionScope(); 6357 if (transformAsUpValueFunc(newExp(unary_exp, unary_exp), out)) {
6358 out.back() = "(#"s + checkVar + " > 0 and "s + out.back() + ')';
6359 return;
6360 }
6361 pushAnonFunctionScope();
6095 pushAnonVarArg(); 6362 pushAnonVarArg();
6096 pushScope(); 6363 pushScope();
6097 arrayCheck(true); 6364 arrayCheck(true);
@@ -6106,7 +6373,10 @@ private:
6106 } 6373 }
6107 } else { 6374 } else {
6108 if (usage == ExpUsage::Closure) { 6375 if (usage == ExpUsage::Closure) {
6109 pushFunctionScope(); 6376 if (transformAsUpValueFunc(newExp(unary_exp, unary_exp), out)) {
6377 return;
6378 }
6379 pushAnonFunctionScope();
6110 pushAnonVarArg(); 6380 pushAnonVarArg();
6111 pushScope(); 6381 pushScope();
6112 } 6382 }
@@ -6160,7 +6430,10 @@ private:
6160 if (varName.empty()) { 6430 if (varName.empty()) {
6161 str_list temp; 6431 str_list temp;
6162 if (usage == ExpUsage::Closure) { 6432 if (usage == ExpUsage::Closure) {
6163 pushFunctionScope(); 6433 if (transformAsUpValueFunc(newExp(unary_exp, unary_exp), out)) {
6434 return;
6435 }
6436 pushAnonFunctionScope();
6164 pushAnonVarArg(); 6437 pushAnonVarArg();
6165 pushScope(); 6438 pushScope();
6166 } else if (usage == ExpUsage::Assignment) { 6439 } else if (usage == ExpUsage::Assignment) {
@@ -6302,11 +6575,21 @@ private:
6302 void transformSpreadTable(const node_container& values, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 6575 void transformSpreadTable(const node_container& values, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
6303 auto x = values.front(); 6576 auto x = values.front();
6304 switch (usage) { 6577 switch (usage) {
6305 case ExpUsage::Closure: 6578 case ExpUsage::Closure: {
6306 pushFunctionScope(); 6579 auto tableLit = x->new_ptr<TableLit_t>();
6580 for (ast_node* value : values) {
6581 tableLit->values.push_back(value);
6582 }
6583 auto simpleValue = x->new_ptr<SimpleValue_t>();
6584 simpleValue->value.set(tableLit);
6585 if (transformAsUpValueFunc(newExp(simpleValue, x), out)) {
6586 return;
6587 }
6588 pushAnonFunctionScope();
6307 pushAnonVarArg(); 6589 pushAnonVarArg();
6308 pushScope(); 6590 pushScope();
6309 break; 6591 break;
6592 }
6310 case ExpUsage::Assignment: 6593 case ExpUsage::Assignment:
6311 pushScope(); 6594 pushScope();
6312 break; 6595 break;
@@ -6336,7 +6619,7 @@ private:
6336 std::string indexVar = getUnusedName("_idx_"sv); 6619 std::string indexVar = getUnusedName("_idx_"sv);
6337 std::string keyVar = getUnusedName("_key_"sv); 6620 std::string keyVar = getUnusedName("_key_"sv);
6338 std::string valueVar = getUnusedName("_value_"sv); 6621 std::string valueVar = getUnusedName("_value_"sv);
6339 auto objVar = singleVariableFrom(spread->exp, true); 6622 auto objVar = singleVariableFrom(spread->exp, AccessType::Read);
6340 if (objVar.empty()) { 6623 if (objVar.empty()) {
6341 objVar = getUnusedName("_obj_"); 6624 objVar = getUnusedName("_obj_");
6342 auto assignment = toAst<ExpListAssign_t>(objVar + "=nil"s, item); 6625 auto assignment = toAst<ExpListAssign_t>(objVar + "=nil"s, item);
@@ -6360,7 +6643,7 @@ private:
6360 auto spread = static_cast<SpreadListExp_t*>(item); 6643 auto spread = static_cast<SpreadListExp_t*>(item);
6361 std::string indexVar = getUnusedName("_idx_"sv); 6644 std::string indexVar = getUnusedName("_idx_"sv);
6362 std::string valueVar = getUnusedName("_value_"sv); 6645 std::string valueVar = getUnusedName("_value_"sv);
6363 auto objVar = singleVariableFrom(spread->exp, true); 6646 auto objVar = singleVariableFrom(spread->exp, AccessType::Read);
6364 if (objVar.empty()) { 6647 if (objVar.empty()) {
6365 objVar = getUnusedName("_obj_"); 6648 objVar = getUnusedName("_obj_");
6366 auto assignment = toAst<ExpListAssign_t>(objVar + "=nil"s, item); 6649 auto assignment = toAst<ExpListAssign_t>(objVar + "=nil"s, item);
@@ -6704,7 +6987,7 @@ private:
6704 decIndentOffset(); 6987 decIndentOffset();
6705 out.back() += (indent() + '}'); 6988 out.back() += (indent() + '}');
6706 } else { 6989 } else {
6707 auto tabStr = globalVar("setmetatable"sv, x); 6990 auto tabStr = globalVar("setmetatable"sv, x, AccessType::Read);
6708 tabStr += '('; 6991 tabStr += '(';
6709 if (temp.empty()) { 6992 if (temp.empty()) {
6710 decIndentOffset(); 6993 decIndentOffset();
@@ -6825,20 +7108,26 @@ private:
6825 if (!def || def->defVal) { 7108 if (!def || def->defVal) {
6826 throw CompileError("invalid comprehension expression", comp->items.front()); 7109 throw CompileError("invalid comprehension expression", comp->items.front());
6827 } 7110 }
6828 auto value = def->item.get();
6829 auto compInner = static_cast<CompInner_t*>(comp->items.back());
6830 switch (usage) { 7111 switch (usage) {
6831 case ExpUsage::Closure: 7112 case ExpUsage::Closure: {
6832 pushFunctionScope(); 7113 auto simpleValue = x->new_ptr<SimpleValue_t>();
7114 simpleValue->value.set(comp);
7115 if (transformAsUpValueFunc(newExp(simpleValue, x), out)) {
7116 return;
7117 }
7118 pushAnonFunctionScope();
6833 pushAnonVarArg(); 7119 pushAnonVarArg();
6834 pushScope(); 7120 pushScope();
6835 break; 7121 break;
7122 }
6836 case ExpUsage::Assignment: 7123 case ExpUsage::Assignment:
6837 pushScope(); 7124 pushScope();
6838 break; 7125 break;
6839 default: 7126 default:
6840 break; 7127 break;
6841 } 7128 }
7129 auto value = def->item.get();
7130 auto compInner = static_cast<CompInner_t*>(comp->items.back());
6842 str_list temp; 7131 str_list temp;
6843 std::string accumVar = getUnusedName("_accum_"sv); 7132 std::string accumVar = getUnusedName("_accum_"sv);
6844 std::string lenVar = getUnusedName("_len_"sv); 7133 std::string lenVar = getUnusedName("_len_"sv);
@@ -6954,7 +7243,7 @@ private:
6954 switch (loopTarget->get_id()) { 7243 switch (loopTarget->get_id()) {
6955 case id<StarExp_t>(): { 7244 case id<StarExp_t>(): {
6956 auto star_exp = static_cast<StarExp_t*>(loopTarget); 7245 auto star_exp = static_cast<StarExp_t*>(loopTarget);
6957 auto listVar = singleVariableFrom(star_exp->value, true); 7246 auto listVar = singleVariableFrom(star_exp->value, AccessType::Read);
6958 if (!isLocal(listVar)) listVar.clear(); 7247 if (!isLocal(listVar)) listVar.clear();
6959 auto indexVar = getUnusedName("_index_"sv); 7248 auto indexVar = getUnusedName("_index_"sv);
6960 varAfter.push_back(indexVar); 7249 varAfter.push_back(indexVar);
@@ -7430,8 +7719,13 @@ private:
7430 } 7719 }
7431 7720
7432 void transformForClosure(For_t* forNode, str_list& out) { 7721 void transformForClosure(For_t* forNode, str_list& out) {
7722 auto simpleValue = forNode->new_ptr<SimpleValue_t>();
7723 simpleValue->value.set(forNode);
7724 if (transformAsUpValueFunc(newExp(simpleValue, forNode), out)) {
7725 return;
7726 }
7433 str_list temp; 7727 str_list temp;
7434 pushFunctionScope(); 7728 pushAnonFunctionScope();
7435 pushAnonVarArg(); 7729 pushAnonVarArg();
7436 std::string& funcStart = temp.emplace_back(); 7730 std::string& funcStart = temp.emplace_back();
7437 pushScope(); 7731 pushScope();
@@ -7519,8 +7813,13 @@ private:
7519 } 7813 }
7520 7814
7521 void transformForEachClosure(ForEach_t* forEach, str_list& out) { 7815 void transformForEachClosure(ForEach_t* forEach, str_list& out) {
7816 auto simpleValue = forEach->new_ptr<SimpleValue_t>();
7817 simpleValue->value.set(forEach);
7818 if (transformAsUpValueFunc(newExp(simpleValue, forEach), out)) {
7819 return;
7820 }
7522 str_list temp; 7821 str_list temp;
7523 pushFunctionScope(); 7822 pushAnonFunctionScope();
7524 pushAnonVarArg(); 7823 pushAnonVarArg();
7525 std::string& funcStart = temp.emplace_back(); 7824 std::string& funcStart = temp.emplace_back();
7526 pushScope(); 7825 pushScope();
@@ -7569,8 +7868,9 @@ private:
7569 out.push_back(name + " = "s + name); 7868 out.push_back(name + " = "s + name);
7570 } 7869 }
7571 if (_config.lintGlobalVariable && !isLocal(name)) { 7870 if (_config.lintGlobalVariable && !isLocal(name)) {
7572 if (_globals.find(name) == _globals.end()) { 7871 auto key = name + ':' + std::to_string(pair->name->m_begin.m_line) + ':' + std::to_string(pair->name->m_begin.m_col);
7573 _globals[name] = {pair->name->m_begin.m_line, pair->name->m_begin.m_col}; 7872 if (_globals.find(key) != _globals.end()) {
7873 _globals[key] = {name, pair->name->m_begin.m_line, pair->name->m_begin.m_col, _funcLevel > 1 ? AccessType::Capture : AccessType::Read};
7574 } 7874 }
7575 } 7875 }
7576 } 7876 }
@@ -7675,7 +7975,7 @@ private:
7675 } 7975 }
7676 case id<Exp_t>(): { 7976 case id<Exp_t>(): {
7677 transformExp(static_cast<Exp_t*>(content), temp, ExpUsage::Closure); 7977 transformExp(static_cast<Exp_t*>(content), temp, ExpUsage::Closure);
7678 temp.back() = globalVar("tostring"sv, content) + '(' + temp.back() + ')'; 7978 temp.back() = globalVar("tostring"sv, content, AccessType::Read) + '(' + temp.back() + ')';
7679 break; 7979 break;
7680 } 7980 }
7681 default: YUEE("AST node mismatch", content); break; 7981 default: YUEE("AST node mismatch", content); break;
@@ -7708,8 +8008,13 @@ private:
7708 } 8008 }
7709 8009
7710 void transformClassDeclClosure(ClassDecl_t* classDecl, str_list& out) { 8010 void transformClassDeclClosure(ClassDecl_t* classDecl, str_list& out) {
8011 auto simpleValue = classDecl->new_ptr<SimpleValue_t>();
8012 simpleValue->value.set(classDecl);
8013 if (transformAsUpValueFunc(newExp(simpleValue, classDecl), out)) {
8014 return;
8015 }
7711 str_list temp; 8016 str_list temp;
7712 pushFunctionScope(); 8017 pushAnonFunctionScope();
7713 pushAnonVarArg(); 8018 pushAnonVarArg();
7714 std::string& funcStart = temp.emplace_back(); 8019 std::string& funcStart = temp.emplace_back();
7715 pushScope(); 8020 pushScope();
@@ -7918,7 +8223,7 @@ private:
7918 if (extend) { 8223 if (extend) {
7919 _buf << indent() << "setmetatable("sv << baseVar << ", "sv << parentVar << ".__base)"sv << nll(classDecl); 8224 _buf << indent() << "setmetatable("sv << baseVar << ", "sv << parentVar << ".__base)"sv << nll(classDecl);
7920 } 8225 }
7921 _buf << indent() << classVar << " = "sv << globalVar("setmetatable"sv, classDecl) << "({"sv << nll(classDecl); 8226 _buf << indent() << classVar << " = "sv << globalVar("setmetatable"sv, classDecl, AccessType::Read) << "({"sv << nll(classDecl);
7922 if (!builtins.empty()) { 8227 if (!builtins.empty()) {
7923 _buf << join(builtins) << ',' << nll(classDecl); 8228 _buf << join(builtins) << ',' << nll(classDecl);
7924 } else { 8229 } else {
@@ -8142,8 +8447,13 @@ private:
8142 } 8447 }
8143 8448
8144 void transformWithClosure(With_t* with, str_list& out) { 8449 void transformWithClosure(With_t* with, str_list& out) {
8450 auto simpleValue = with->new_ptr<SimpleValue_t>();
8451 simpleValue->value.set(with);
8452 if (transformAsUpValueFunc(newExp(simpleValue, with), out)) {
8453 return;
8454 }
8145 str_list temp; 8455 str_list temp;
8146 pushFunctionScope(); 8456 pushAnonFunctionScope();
8147 pushAnonVarArg(); 8457 pushAnonVarArg();
8148 std::string& funcStart = temp.emplace_back(); 8458 std::string& funcStart = temp.emplace_back();
8149 pushScope(); 8459 pushScope();
@@ -8163,9 +8473,9 @@ private:
8163 bool scoped = false; 8473 bool scoped = false;
8164 if (with->assigns) { 8474 if (with->assigns) {
8165 auto vars = getAssignVars(with); 8475 auto vars = getAssignVars(with);
8166 if (vars.front().empty() || isGlobal(vars.front())) { 8476 if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) {
8167 if (with->assigns->values.objects().size() == 1) { 8477 if (with->assigns->values.objects().size() == 1) {
8168 auto var = singleVariableFrom(with->assigns->values.objects().front(), true); 8478 auto var = singleVariableFrom(with->assigns->values.objects().front(), AccessType::Read);
8169 if (!var.empty() && isLocal(var)) { 8479 if (!var.empty() && isLocal(var)) {
8170 withVar = var; 8480 withVar = var;
8171 } 8481 }
@@ -8211,7 +8521,7 @@ private:
8211 transformAssignment(assignment, temp); 8521 transformAssignment(assignment, temp);
8212 } 8522 }
8213 } else { 8523 } else {
8214 withVar = singleVariableFrom(with->valueList, true); 8524 withVar = singleVariableFrom(with->valueList, AccessType::Read);
8215 if (withVar.empty() || !isLocal(withVar)) { 8525 if (withVar.empty() || !isLocal(withVar)) {
8216 withVar = getUnusedName("_with_"sv); 8526 withVar = getUnusedName("_with_"sv);
8217 auto assignment = x->new_ptr<ExpListAssign_t>(); 8527 auto assignment = x->new_ptr<ExpListAssign_t>();
@@ -8555,11 +8865,17 @@ private:
8555 8865
8556 void transformTblComprehension(TblComprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 8866 void transformTblComprehension(TblComprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
8557 switch (usage) { 8867 switch (usage) {
8558 case ExpUsage::Closure: 8868 case ExpUsage::Closure: {
8559 pushFunctionScope(); 8869 auto simpleValue = comp->new_ptr<SimpleValue_t>();
8870 simpleValue->value.set(comp);
8871 if (transformAsUpValueFunc(newExp(simpleValue, comp), out)) {
8872 return;
8873 }
8874 pushAnonFunctionScope();
8560 pushAnonVarArg(); 8875 pushAnonVarArg();
8561 pushScope(); 8876 pushScope();
8562 break; 8877 break;
8878 }
8563 case ExpUsage::Assignment: 8879 case ExpUsage::Assignment:
8564 pushScope(); 8880 pushScope();
8565 break; 8881 break;
@@ -8663,7 +8979,12 @@ private:
8663 str_list temp; 8979 str_list temp;
8664 std::string* funcStart = nullptr; 8980 std::string* funcStart = nullptr;
8665 if (usage == ExpUsage::Closure) { 8981 if (usage == ExpUsage::Closure) {
8666 pushFunctionScope(); 8982 auto simpleValue = doNode->new_ptr<SimpleValue_t>();
8983 simpleValue->value.set(doNode);
8984 if (transformAsUpValueFunc(newExp(simpleValue, doNode), out)) {
8985 return;
8986 }
8987 pushAnonFunctionScope();
8667 pushAnonVarArg(); 8988 pushAnonVarArg();
8668 funcStart = &temp.emplace_back(); 8989 funcStart = &temp.emplace_back();
8669 } else { 8990 } else {
@@ -8691,7 +9012,7 @@ private:
8691 errHandler.set(toAst<Exp_t>(errHandleStr, x->func)); 9012 errHandler.set(toAst<Exp_t>(errHandleStr, x->func));
8692 auto funLit = simpleSingleValueFrom(errHandler)->value.to<FunLit_t>(); 9013 auto funLit = simpleSingleValueFrom(errHandler)->value.to<FunLit_t>();
8693 auto body = x->new_ptr<Body_t>(); 9014 auto body = x->new_ptr<Body_t>();
8694 body->content.set(tryNode->catchBlock->body); 9015 body->content.set(tryNode->catchBlock->block);
8695 funLit->body.set(body); 9016 funLit->body.set(body);
8696 } 9017 }
8697 if (auto tryBlock = tryNode->func.as<Block_t>()) { 9018 if (auto tryBlock = tryNode->func.as<Block_t>()) {
@@ -8709,6 +9030,35 @@ private:
8709 BLOCK_END 9030 BLOCK_END
8710 } 9031 }
8711 if (auto tryBlock = tryNode->func.as<Block_t>()) { 9032 if (auto tryBlock = tryNode->func.as<Block_t>()) {
9033 {
9034 auto body = tryBlock->new_ptr<Body_t>();
9035 body->content.set(tryBlock);
9036 auto doNode = tryBlock->new_ptr<Do_t>();
9037 doNode->body.set(body);
9038 auto simpleValue = tryBlock->new_ptr<SimpleValue_t>();
9039 simpleValue->value.set(doNode);
9040 if (auto result = upValueFuncFrom(newExp(simpleValue, tryBlock))) {
9041 auto [funcName, args] = std::move(*result);
9042 if (errHandler) {
9043 auto xpcall = toAst<ChainValue_t>("xpcall()", x);
9044 auto invoke = ast_to<Invoke_t>(xpcall->items.back());
9045 invoke->args.push_back(toAst<Exp_t>(funcName, x));
9046 invoke->args.push_back(errHandler);
9047 invoke->args.dup(toAst<ExpList_t>(join(args, ","sv), x)->exprs);
9048 transformChainValue(xpcall, out, ExpUsage::Closure);
9049 } else {
9050 auto pcall = toAst<ChainValue_t>("pcall()", x);
9051 auto invoke = ast_to<Invoke_t>(pcall->items.back());
9052 invoke->args.push_back(toAst<Exp_t>(funcName, x));
9053 invoke->args.dup(toAst<ExpList_t>(join(args, ","sv), x)->exprs);
9054 transformChainValue(pcall, out, ExpUsage::Closure);
9055 }
9056 if (usage == ExpUsage::Common) {
9057 out.back().append(nlr(x));
9058 }
9059 return;
9060 }
9061 }
8712 auto tryExp = toAst<Exp_t>("->"sv, x); 9062 auto tryExp = toAst<Exp_t>("->"sv, x);
8713 auto funLit = simpleSingleValueFrom(tryExp)->value.to<FunLit_t>(); 9063 auto funLit = simpleSingleValueFrom(tryExp)->value.to<FunLit_t>();
8714 auto body = x->new_ptr<Body_t>(); 9064 auto body = x->new_ptr<Body_t>();
@@ -8806,7 +9156,7 @@ private:
8806 void transformImportFrom(ImportFrom_t* importNode, str_list& out) { 9156 void transformImportFrom(ImportFrom_t* importNode, str_list& out) {
8807 str_list temp; 9157 str_list temp;
8808 auto x = importNode; 9158 auto x = importNode;
8809 auto objVar = singleVariableFrom(importNode->item, true); 9159 auto objVar = singleVariableFrom(importNode->item, AccessType::Read);
8810 ast_ptr<false, ExpListAssign_t> objAssign; 9160 ast_ptr<false, ExpListAssign_t> objAssign;
8811 if (objVar.empty()) { 9161 if (objVar.empty()) {
8812 objVar = getUnusedName("_obj_"sv); 9162 objVar = getUnusedName("_obj_"sv);
@@ -9169,8 +9519,13 @@ private:
9169 9519
9170 void transformWhileClosure(While_t* whileNode, str_list& out) { 9520 void transformWhileClosure(While_t* whileNode, str_list& out) {
9171 auto x = whileNode; 9521 auto x = whileNode;
9522 auto simpleValue = x->new_ptr<SimpleValue_t>();
9523 simpleValue->value.set(whileNode);
9524 if (transformAsUpValueFunc(newExp(simpleValue, x), out)) {
9525 return;
9526 }
9172 str_list temp; 9527 str_list temp;
9173 pushFunctionScope(); 9528 pushAnonFunctionScope();
9174 pushAnonVarArg(); 9529 pushAnonVarArg();
9175 std::string& funcStart = temp.emplace_back(); 9530 std::string& funcStart = temp.emplace_back();
9176 pushScope(); 9531 pushScope();
@@ -9232,13 +9587,18 @@ private:
9232 str_list temp; 9587 str_list temp;
9233 std::string* funcStart = nullptr; 9588 std::string* funcStart = nullptr;
9234 if (usage == ExpUsage::Closure) { 9589 if (usage == ExpUsage::Closure) {
9235 pushFunctionScope(); 9590 auto simpleValue = x->new_ptr<SimpleValue_t>();
9591 simpleValue->value.set(switchNode);
9592 if (transformAsUpValueFunc(newExp(simpleValue, x), out)) {
9593 return;
9594 }
9595 pushAnonFunctionScope();
9236 pushAnonVarArg(); 9596 pushAnonVarArg();
9237 funcStart = &temp.emplace_back(); 9597 funcStart = &temp.emplace_back();
9238 pushScope(); 9598 pushScope();
9239 } 9599 }
9240 bool extraScope = false; 9600 bool extraScope = false;
9241 auto objVar = singleVariableFrom(switchNode->target, true); 9601 auto objVar = singleVariableFrom(switchNode->target, AccessType::Read);
9242 if (objVar.empty() || !isLocal(objVar)) { 9602 if (objVar.empty() || !isLocal(objVar)) {
9243 if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { 9603 if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) {
9244 extraScope = true; 9604 extraScope = true;
@@ -9285,7 +9645,7 @@ private:
9285 forceAddToScope(typeVar); 9645 forceAddToScope(typeVar);
9286 tabCheckVar = getUnusedName("_tab_"sv); 9646 tabCheckVar = getUnusedName("_tab_"sv);
9287 forceAddToScope(tabCheckVar); 9647 forceAddToScope(tabCheckVar);
9288 temp.push_back(indent() + "local "s + typeVar + " = "s + globalVar("type"sv, branch) + '(' + objVar + ')' + nll(branch)); 9648 temp.push_back(indent() + "local "s + typeVar + " = "s + globalVar("type"sv, branch, AccessType::Read) + '(' + objVar + ')' + nll(branch));
9289 temp.push_back(indent() + "local "s + tabCheckVar + " = \"table\" == "s + typeVar + " or \"userdata\" == "s + typeVar + nll(branch)); 9649 temp.push_back(indent() + "local "s + tabCheckVar + " = \"table\" == "s + typeVar + " or \"userdata\" == "s + typeVar + nll(branch));
9290 } 9650 }
9291 std::string matchVar; 9651 std::string matchVar;
@@ -9730,12 +10090,12 @@ private:
9730 constVal = ast_is<ConstValue_t, Num_t>(simpleVal->value); 10090 constVal = ast_is<ConstValue_t, Num_t>(simpleVal->value);
9731 } 10091 }
9732 bool localVal = false; 10092 bool localVal = false;
9733 if (auto var = singleVariableFrom(value, false); isLocal(var)) { 10093 if (auto var = singleVariableFrom(value, AccessType::None); isLocal(var)) {
9734 localVal = true; 10094 localVal = true;
9735 } 10095 }
9736 if (!constVal && !localVal) { 10096 if (!constVal && !localVal) {
9737 for (auto exp : chainAssign->exprs.objects()) { 10097 for (auto exp : chainAssign->exprs.objects()) {
9738 std::string var = singleVariableFrom(exp, false); 10098 std::string var = singleVariableFrom(exp, AccessType::None);
9739 if (!var.empty()) { 10099 if (!var.empty()) {
9740 str_list temp; 10100 str_list temp;
9741 transformAssignment(assignmentFrom(static_cast<Exp_t*>(exp), value, exp), temp); 10101 transformAssignment(assignmentFrom(static_cast<Exp_t*>(exp), value, exp), temp);
diff --git a/src/yuescript/yue_compiler.h b/src/yuescript/yue_compiler.h
index a781b58..8c8ea61 100644
--- a/src/yuescript/yue_compiler.h
+++ b/src/yuescript/yue_compiler.h
@@ -39,10 +39,18 @@ struct YueConfig {
39 Options options; 39 Options options;
40}; 40};
41 41
42enum class AccessType {
43 None,
44 Read,
45 Capture,
46 Write
47};
48
42struct GlobalVar { 49struct GlobalVar {
43 std::string name; 50 std::string name;
44 int line; 51 int line;
45 int col; 52 int col;
53 AccessType accessType;
46}; 54};
47 55
48using GlobalVars = std::vector<GlobalVar>; 56using GlobalVars = std::vector<GlobalVar>;
@@ -60,6 +68,7 @@ struct CompileInfo {
60 std::unique_ptr<Options> options; 68 std::unique_ptr<Options> options;
61 double parseTime; 69 double parseTime;
62 double compileTime; 70 double compileTime;
71 bool usedVar;
63 72
64 CompileInfo() { } 73 CompileInfo() { }
65 CompileInfo( 74 CompileInfo(
@@ -68,7 +77,8 @@ struct CompileInfo {
68 std::unique_ptr<GlobalVars>&& globals, 77 std::unique_ptr<GlobalVars>&& globals,
69 std::unique_ptr<Options>&& options, 78 std::unique_ptr<Options>&& options,
70 double parseTime, 79 double parseTime,
71 double compileTime); 80 double compileTime,
81 bool usedVar);
72 CompileInfo(CompileInfo&& other); 82 CompileInfo(CompileInfo&& other);
73 void operator=(CompileInfo&& other); 83 void operator=(CompileInfo&& other);
74}; 84};