From 1890294226034d27165af016c8c93a484d978b49 Mon Sep 17 00:00:00 2001
From: Li Jin <dragon-fly@qq.com>
Date: Thu, 23 May 2024 16:30:05 +0800
Subject: prevent more anonymous functions generating from `const`, `close`
 decl.

---
 spec/outputs/5.1/attrib.lua     | 115 +++++++++++++++++++---------------------
 spec/outputs/attrib.lua         |  94 ++++++++++++++++----------------
 spec/outputs/compile_doc.lua    |  70 ++++++++++++------------
 spec/outputs/unicode/attrib.lua |  96 ++++++++++++++++-----------------
 src/yuescript/yue_compiler.cpp  |  48 ++++++++++++-----
 5 files changed, 221 insertions(+), 202 deletions(-)

diff --git a/spec/outputs/5.1/attrib.lua b/spec/outputs/5.1/attrib.lua
index 8361b24..c48c72c 100644
--- a/spec/outputs/5.1/attrib.lua
+++ b/spec/outputs/5.1/attrib.lua
@@ -55,22 +55,16 @@ local _anon_func_0 = function(_close_1, error, f, _arg_0, ...)
 		end
 	end
 end
-local _anon_func_1 = function(io)
-	local _with_0 = io.open("file.txt")
-	_with_0:write("Hello")
-	return _with_0
-end
-local _anon_func_2 = function() end
+local _anon_func_1 = function() end
 do
-	local v = (function()
-		if flag then
-			return func()
-		else
-			return setmetatable({ }, {
-				__close = function(self) end
-			})
-		end
-	end)()
+	local v
+	if flag then
+		v = func()
+	else
+		v = setmetatable({ }, {
+			__close = function(self) end
+		})
+	end
 	local _close_0 = assert(getmetatable(v).__close);
 	(function(_arg_0, ...)
 		local _ok_0 = _arg_0
@@ -81,12 +75,17 @@ do
 			return error(...)
 		end
 	end)(pcall(function()
-		local f = _anon_func_1(io)
+		local f
+		do
+			local _with_0 = io.open("file.txt")
+			_with_0:write("Hello")
+			f = _with_0
+		end
 		local _close_1 = assert(getmetatable(f).__close)
-		return _anon_func_0(_close_1, error, f, pcall(_anon_func_2))
+		return _anon_func_0(_close_1, error, f, pcall(_anon_func_1))
 	end))
 end
-local _anon_func_3 = function(_close_1, d, error, _arg_0, ...)
+local _anon_func_2 = function(_close_1, d, error, _arg_0, ...)
 	do
 		local _ok_0 = _arg_0
 		_close_1(d)
@@ -97,41 +96,25 @@ local _anon_func_3 = function(_close_1, d, error, _arg_0, ...)
 		end
 	end
 end
-local _anon_func_4 = function(x)
-	if true then
-		if "abc" == x then
-			return 998
-		end
-	end
-end
-local _anon_func_6 = function(a, b)
+local _anon_func_3 = function(a, b)
 	if a ~= nil then
 		return a
 	else
 		return b
 	end
 end
-local _anon_func_5 = function(a, b)
-	if _anon_func_6(a, b) then
-		return {
-			value = value
-		}
-	end
-end
-local _anon_func_7 = function() end
+local _anon_func_4 = function() end
 do
-	local a = (function()
-		if true then
-			return 1
-		end
-	end)()
-	local b = (function()
-		if not false then
-			if x then
-				return 1
-			end
+	local a
+	if true then
+		a = 1
+	end
+	local b
+	if not false then
+		if x then
+			b = 1
 		end
-	end)()
+	end
 	local _close_0 = assert(getmetatable(b).__close);
 	(function(_arg_0, ...)
 		local _ok_0 = _arg_0
@@ -142,13 +125,24 @@ do
 			return error(...)
 		end
 	end)(pcall(function()
-		local c = _anon_func_4(x)
-		local d = _anon_func_5(a, b)
+		local c
+		if true then
+			local _exp_0 = x
+			if "abc" == _exp_0 then
+				c = 998
+			end
+		end
+		local d
+		if _anon_func_3(a, b) then
+			d = {
+				value = value
+			}
+		end
 		local _close_1 = assert(getmetatable(d).__close)
-		return _anon_func_3(_close_1, d, error, pcall(_anon_func_7))
+		return _anon_func_2(_close_1, d, error, pcall(_anon_func_4))
 	end))
 end
-local _anon_func_8 = function(_, _close_1, error, _arg_0, ...)
+local _anon_func_5 = function(_, _close_1, error, _arg_0, ...)
 	do
 		local _ok_0 = _arg_0
 		_close_1(_)
@@ -159,7 +153,7 @@ local _anon_func_8 = function(_, _close_1, error, _arg_0, ...)
 		end
 	end
 end
-local _anon_func_9 = function(_, _close_2, error, _arg_0, ...)
+local _anon_func_6 = function(_, _close_2, error, _arg_0, ...)
 	do
 		local _ok_0 = _arg_0
 		_close_2(_)
@@ -171,11 +165,12 @@ local _anon_func_9 = function(_, _close_2, error, _arg_0, ...)
 	end
 end
 do
-	local _ = (function()
+	local _
+	do
 		local _with_0 = io.open("file.txt")
 		_with_0:write("Hello")
-		return _with_0
-	end)()
+		_ = _with_0
+	end
 	local _close_0 = assert(getmetatable(_).__close);
 	(function(_arg_0, ...)
 		local _ok_0 = _arg_0
@@ -192,14 +187,14 @@ do
 			end
 		})
 		local _close_1 = assert(getmetatable(_).__close)
-		return _anon_func_8(_, _close_1, error, pcall(function()
+		return _anon_func_5(_, _close_1, error, pcall(function()
 			local _ = setmetatable({ }, {
 				__close = function()
 					return print("first")
 				end
 			})
 			local _close_2 = assert(getmetatable(_).__close)
-			return _anon_func_9(_, _close_2, error, pcall(function()
+			return _anon_func_6(_, _close_2, error, pcall(function()
 				return print("third")
 			end))
 		end))
@@ -216,7 +211,7 @@ def = function(item)
 	_defers[#_defers + 1] = item
 	return _defers
 end
-local _anon_func_10 = function(_, _close_1, error, _arg_0, ...)
+local _anon_func_7 = function(_, _close_1, error, _arg_0, ...)
 	do
 		local _ok_0 = _arg_0
 		_close_1(_)
@@ -227,7 +222,7 @@ local _anon_func_10 = function(_, _close_1, error, _arg_0, ...)
 		end
 	end
 end
-local _anon_func_11 = function(_, _close_2, error, _arg_0, ...)
+local _anon_func_8 = function(_, _close_2, error, _arg_0, ...)
 	do
 		local _ok_0 = _arg_0
 		_close_2(_)
@@ -238,7 +233,7 @@ local _anon_func_11 = function(_, _close_2, error, _arg_0, ...)
 		end
 	end
 end
-local _anon_func_12 = function() end
+local _anon_func_9 = function() end
 do
 	local _ = def(function()
 		return print(3)
@@ -257,12 +252,12 @@ do
 			return print(2)
 		end)
 		local _close_1 = assert(getmetatable(_).__close)
-		return _anon_func_10(_, _close_1, error, pcall(function()
+		return _anon_func_7(_, _close_1, error, pcall(function()
 			local _ = def(function()
 				return print(1)
 			end)
 			local _close_2 = assert(getmetatable(_).__close)
-			return _anon_func_11(_, _close_2, error, pcall(_anon_func_12))
+			return _anon_func_8(_, _close_2, error, pcall(_anon_func_9))
 		end))
 	end))
 end
diff --git a/spec/outputs/attrib.lua b/spec/outputs/attrib.lua
index 626944e..e48963c 100644
--- a/spec/outputs/attrib.lua
+++ b/spec/outputs/attrib.lua
@@ -34,62 +34,62 @@ do
 	a, b = _obj_0[1], _obj_0[2]
 end
 do
-	local v <close> = (function()
-		if flag then
-			return func()
-		else
-			return setmetatable({ }, {
-				__close = function(self) end
-			})
-		end
-	end)()
-	local f <close> = (function()
-		local _with_0 = io.open("file.txt")
-		_with_0:write("Hello")
-		return _with_0
-	end)()
+	local v
+	if flag then
+		v = func()
+	else
+		v = setmetatable({ }, {
+			__close = function(self) end
+		})
+	end
+	local _close_0 <close> = v
+	local f
+	local _with_0 = io.open("file.txt")
+	_with_0:write("Hello")
+	f = _with_0
+	local _close_1 <close> = f
 end
 do
-	local a <const> = (function()
-		if true then
-			return 1
-		end
-	end)()
-	local b <close> = (function()
-		if not false then
-			if x then
-				return 1
-			end
+	local a
+	if true then
+		a = 1
+	end
+	local b
+	if not false then
+		if x then
+			b = 1
 		end
-	end)()
-	local c <const> = (function()
-		if true then
-			local _exp_0 = x
-			if "abc" == _exp_0 then
-				return 998
-			end
+	end
+	local _close_0 <close> = b
+	local c
+	if true then
+		local _exp_0 = x
+		if "abc" == _exp_0 then
+			c = 998
 		end
-	end)()
-	local d <close> = (function()
-		if (function()
-			if a ~= nil then
-				return a
-			else
-				return b
-			end
-		end)() then
-			return {
-				value = value
-			}
+	end
+	local d
+	if (function()
+		if a ~= nil then
+			return a
+		else
+			return b
 		end
-	end)()
+	end)() then
+		d = {
+			value = value
+		}
+	end
+	local _close_1 <close> = d
 end
 do
-	local _ <close> = (function()
+	local _
+	do
 		local _with_0 = io.open("file.txt")
 		_with_0:write("Hello")
-		return _with_0
-	end)()
+		_ = _with_0
+	end
+	local _close_0 <close> = _
 	local _ <close> = setmetatable({ }, {
 		__close = function()
 			return print("second")
diff --git a/spec/outputs/compile_doc.lua b/spec/outputs/compile_doc.lua
index 29f4aeb..3781fb9 100644
--- a/spec/outputs/compile_doc.lua
+++ b/spec/outputs/compile_doc.lua
@@ -12,42 +12,42 @@ local _list_0 = {
 for _index_0 = 1, #_list_0 do
 	local _des_0 = _list_0[_index_0]
 	local compiledFile, docFile = _des_0[1], _des_0[2]
-	local input <close> = (function()
-		local _with_0 = io.open(docFile)
-		if _with_0 ~= nil then
-			local to_lua = require("yue").to_lua
-			local text = _with_0:read("*a")
-			local codes = { }
-			for code in text:gmatch("```moonscript(.-)```") do
-				local result, err = to_lua(code, {
-					implicit_return_root = false,
-					reserve_line_number = false
-				})
-				if result then
-					codes[#codes + 1] = result
-				elseif not err:match("macro exporting module only accepts macro definition") then
-					print(err)
-					os.exit(1)
-				end
+	local input
+	local _with_0 = io.open(docFile)
+	if _with_0 ~= nil then
+		local to_lua = require("yue").to_lua
+		local text = _with_0:read("*a")
+		local codes = { }
+		for code in text:gmatch("```moonscript(.-)```") do
+			local result, err = to_lua(code, {
+				implicit_return_root = false,
+				reserve_line_number = false
+			})
+			if result then
+				codes[#codes + 1] = result
+			elseif not err:match("macro exporting module only accepts macro definition") then
+				print(err)
+				os.exit(1)
 			end
-			for code in text:gmatch("<pre>(.-)</pre>") do
-				local result, err = to_lua(code:gsub("&lt;", "<"):gsub("&gt;", ">"), {
-					implicit_return_root = false,
-					reserve_line_number = false
-				})
-				if result then
-					codes[#codes + 1] = result
-				else
-					print(err)
-					os.exit(1)
-				end
+		end
+		for code in text:gmatch("<pre>(.-)</pre>") do
+			local result, err = to_lua(code:gsub("&lt;", "<"):gsub("&gt;", ">"), {
+				implicit_return_root = false,
+				reserve_line_number = false
+			})
+			if result then
+				codes[#codes + 1] = result
+			else
+				print(err)
+				os.exit(1)
 			end
-			local output <close> = (function()
-				local _with_1 = io.open(tostring(outputFolder) .. "/" .. tostring(compiledFile), "w+")
-				_with_1:write(table.concat(codes))
-				return _with_1
-			end)()
 		end
-		return _with_0
-	end)()
+		local output
+		local _with_1 = io.open(tostring(outputFolder) .. "/" .. tostring(compiledFile), "w+")
+		_with_1:write(table.concat(codes))
+		output = _with_1
+		local _close_0 <close> = output
+	end
+	input = _with_0
+	local _close_0 <close> = input
 end
diff --git a/spec/outputs/unicode/attrib.lua b/spec/outputs/unicode/attrib.lua
index 58ad4b2..1c48de4 100644
--- a/spec/outputs/unicode/attrib.lua
+++ b/spec/outputs/unicode/attrib.lua
@@ -26,63 +26,63 @@ do
 	_u5143_u7d20d = _obj_2[1]
 end
 do
-	local _u5173_u95ed_u53d8_u91cfv <close> = (function()
-		if _u6807_u8bb0_u4e3a_u771f then
-			return _u51fd_u6570_u8c03_u7528()
-		else
-			return setmetatable({ }, {
-				__close = function(self) end
-			})
-		end
-	end)()
-	local _u5173_u95ed_u53d8_u91cff <close> = (function()
-		local _with_0 = io.open("文件.txt")
-		_with_0:write("你好")
-		return _with_0
-	end)()
+	local _u5173_u95ed_u53d8_u91cfv
+	if _u6807_u8bb0_u4e3a_u771f then
+		_u5173_u95ed_u53d8_u91cfv = _u51fd_u6570_u8c03_u7528()
+	else
+		_u5173_u95ed_u53d8_u91cfv = setmetatable({ }, {
+			__close = function(self) end
+		})
+	end
+	local _close_0 <close> = _u5173_u95ed_u53d8_u91cfv
+	local _u5173_u95ed_u53d8_u91cff
+	local _with_0 = io.open("文件.txt")
+	_with_0:write("你好")
+	_u5173_u95ed_u53d8_u91cff = _with_0
+	local _close_1 <close> = _u5173_u95ed_u53d8_u91cff
 end
 do
-	local _u5e38_u91cfa <const> = (function()
-		if true then
-			return 1
-		end
-	end)()
-	local _u5173_u95ed_u53d8_u91cfb <close> = (function()
-		if not false then
-			if _u6761_u4ef6x then
-				return 1
-			end
+	local _u5e38_u91cfa
+	if true then
+		_u5e38_u91cfa = 1
+	end
+	local _u5173_u95ed_u53d8_u91cfb
+	if not false then
+		if _u6761_u4ef6x then
+			_u5173_u95ed_u53d8_u91cfb = 1
 		end
-	end)()
-	local _u5e38_u91cfc <const> = (function()
-		if true then
-			local _exp_0 = _u6761_u4ef6x
-			if "abc" == _exp_0 then
-				return 998
-			end
+	end
+	local _close_0 <close> = _u5173_u95ed_u53d8_u91cfb
+	local _u5e38_u91cfc
+	if true then
+		local _exp_0 = _u6761_u4ef6x
+		if "abc" == _exp_0 then
+			_u5e38_u91cfc = 998
 		end
-	end)()
-	local _u5173_u95ed_u53d8_u91cfd <close> = (function()
-		if (function()
-			local _exp_0 = _u6761_u4ef6a
-			if _exp_0 ~= nil then
-				return _exp_0
-			else
-				return _u6761_u4ef6b
-			end
-		end)() then
-			return {
-				["数值"] = _u6570_u503c
-			}
+	end
+	local _u5173_u95ed_u53d8_u91cfd
+	if (function()
+		local _exp_0 = _u6761_u4ef6a
+		if _exp_0 ~= nil then
+			return _exp_0
+		else
+			return _u6761_u4ef6b
 		end
-	end)()
+	end)() then
+		_u5173_u95ed_u53d8_u91cfd = {
+			["数值"] = _u6570_u503c
+		}
+	end
+	local _close_1 <close> = _u5173_u95ed_u53d8_u91cfd
 end
 do
-	local __u65e0_u6548_u53d8_u91cf <close> = (function()
+	local __u65e0_u6548_u53d8_u91cf
+	do
 		local _with_0 = io.open("文件.txt")
 		_with_0:write("你好")
-		return _with_0
-	end)()
+		__u65e0_u6548_u53d8_u91cf = _with_0
+	end
+	local _close_0 <close> = __u65e0_u6548_u53d8_u91cf
 	local __u65e0_u6548_u53d8_u91cf <close> = setmetatable({ }, {
 		__close = function()
 			return _u6253_u5370("第二")
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 7f6a042..04874d5 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -75,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = {
 	"close"s // Lua 5.4
 };
 
-const std::string_view version = "0.23.6"sv;
+const std::string_view version = "0.23.7"sv;
 const std::string_view extension = "yue"sv;
 
 class CompileError : public std::logic_error {
@@ -10294,10 +10294,25 @@ private:
 			if (j != je) ++j;
 		}
 		bool checkValuesLater = false;
-		if (listA->names.size() > assignA->values.size()) {
+		for (ast_node* value : assignA->values.objects()) {
+			if (ast_is<Exp_t>(value)) {
+				if (auto sVal = singleValueFrom(value)) {
+					if (auto spValue = sVal->item.as<SimpleValue_t>()) {
+						if (auto funLit = spValue->value.as<FunLit_t>()) {
+							if (!funLit->noRecursion) {
+								checkValuesLater = true;
+							}
+							break;
+						}
+					}
+				}
+			}
+		}
+		if (!checkValuesLater && assignA->values.size() > 0 && listA->names.size() >= assignA->values.size()) {
 			BLOCK_START
 			switch (assignA->values.back()->get_id()) {
 				case id<If_t>():
+				case id<With_t>():
 				case id<Switch_t>():
 					checkValuesLater = true;
 					break;
@@ -10305,24 +10320,33 @@ private:
 			BREAK_IF(checkValuesLater);
 			auto value = singleValueFrom(assignA->values.back());
 			if (!value) {
-				_buf << listA->names.size() << " right values expected, got "sv << assignA->values.size();
-				throw CompileError(clearBuf(), assignA->values.front());
+				if (listA->names.size() > assignA->values.size()) {
+					_buf << listA->names.size() << " right values expected, got "sv << assignA->values.size();
+					throw CompileError(clearBuf(), assignA->values.front());
+				} else {
+					break;
+				}
 			}
 			if (auto val = value->item.as<SimpleValue_t>()) {
 				switch (val->value->get_id()) {
-					case id<If_t>():
-					case id<Switch_t>():
-					case id<Do_t>():
-					case id<Try_t>():
+					case id<TableLit_t>():
+					case id<ConstValue_t>():
+					case id<UnaryValue_t>():
+					case id<Num_t>():
+					case id<VarArg_t>():
+						break;
+					default:
 						checkValuesLater = true;
 						break;
 				}
 				BREAK_IF(checkValuesLater);
 			}
-			auto chainValue = value->item.as<ChainValue_t>();
-			if (!chainValue || !ast_is<Invoke_t, InvokeArgs_t>(chainValue->items.back())) {
-				_buf << listA->names.size() << " right values expected, got "sv << assignA->values.size();
-				throw CompileError(clearBuf(), assignA->values.front());
+			if (listA->names.size() > assignA->values.size()) {
+				auto chainValue = value->item.as<ChainValue_t>();
+				if (!chainValue || !ast_is<Invoke_t, InvokeArgs_t>(chainValue->items.back())) {
+					_buf << listA->names.size() << " right values expected, got "sv << assignA->values.size();
+					throw CompileError(clearBuf(), assignA->values.front());
+				}
 			}
 			BLOCK_END
 		}
-- 
cgit v1.2.3-55-g6feb