From 7575fe00aad91e0ba943e877ddcd838f76e095c0 Mon Sep 17 00:00:00 2001
From: Li Jin <dragon-fly@qq.com>
Date: Thu, 26 Sep 2024 22:11:13 +0800
Subject: Fixed a few issues.

* Fixed a `with` block with return statement issue.
* Fixed a switch-when indentation issue.
* Added error reporting for `return` statement not appearing in last block line.
---
 spec/inputs/syntax.yue          |  4 ++--
 spec/inputs/unicode/syntax.yue  |  4 ++--
 spec/outputs/syntax.lua         | 14 +++++++++-----
 spec/outputs/unicode/syntax.lua | 14 +++++++++-----
 spec/outputs/unicode/with.lua   |  4 +++-
 spec/outputs/with.lua           |  4 +++-
 src/yuescript/yue_compiler.cpp  | 39 ++++++++++++++++++++++++++++++++++++---
 src/yuescript/yue_parser.cpp    |  4 ++--
 8 files changed, 66 insertions(+), 21 deletions(-)

diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue
index 271f43f..a414d6f 100644
--- a/spec/inputs/syntax.yue
+++ b/spec/inputs/syntax.yue
@@ -52,9 +52,9 @@ _ = ->
 
 _ = -> 1,2,34
 
-return 5 + () -> 4 + 2
+do return 5 + () -> 4 + 2
 
-return 5 + (() -> 4) + 2
+do return 5 + (() -> 4) + 2
 
 print 5 + () ->
 	_ = 34
diff --git a/spec/inputs/unicode/syntax.yue b/spec/inputs/unicode/syntax.yue
index f382688..8a98416 100644
--- a/spec/inputs/unicode/syntax.yue
+++ b/spec/inputs/unicode/syntax.yue
@@ -51,9 +51,9 @@ _ = ->
 
 _ = -> 1,2,34
 
-return 5 + () -> 4 + 2
+do return 5 + () -> 4 + 2
 
-return 5 + (() -> 4) + 2
+do return 5 + (() -> 4) + 2
 
 打印 5 + () ->
 	_ = 34
diff --git a/spec/outputs/syntax.lua b/spec/outputs/syntax.lua
index cfe63eb..5fd1821 100644
--- a/spec/outputs/syntax.lua
+++ b/spec/outputs/syntax.lua
@@ -40,12 +40,16 @@ end
 _ = function()
 	return 1, 2, 34
 end
-return 5 + function()
-	return 4 + 2
+do
+	return 5 + function()
+		return 4 + 2
+	end
+end
+do
+	return 5 + (function()
+		return 4
+	end) + 2
 end
-return 5 + (function()
-	return 4
-end) + 2
 print(5 + function()
 	_ = 34
 	return good(nads)
diff --git a/spec/outputs/unicode/syntax.lua b/spec/outputs/unicode/syntax.lua
index 9ea8f68..ea97bb9 100644
--- a/spec/outputs/unicode/syntax.lua
+++ b/spec/outputs/unicode/syntax.lua
@@ -40,12 +40,16 @@ end
 _ = function()
 	return 1, 2, 34
 end
-return 5 + function()
-	return 4 + 2
+do
+	return 5 + function()
+		return 4 + 2
+	end
+end
+do
+	return 5 + (function()
+		return 4
+	end) + 2
 end
-return 5 + (function()
-	return 4
-end) + 2
 _u6253_u5370(5 + function()
 	_ = 34
 	return _u597d(_u7403)
diff --git a/spec/outputs/unicode/with.lua b/spec/outputs/unicode/with.lua
index 7a5ba00..cfad264 100644
--- a/spec/outputs/unicode/with.lua
+++ b/spec/outputs/unicode/with.lua
@@ -123,7 +123,9 @@ do
 	local _
 	_ = function()
 		local _with_0 = _u55e8
-		return _with_0.a, _with_0.b
+		do
+			return _with_0.a, _with_0.b
+		end
 	end
 end
 do
diff --git a/spec/outputs/with.lua b/spec/outputs/with.lua
index b2a1c3b..d880d1e 100644
--- a/spec/outputs/with.lua
+++ b/spec/outputs/with.lua
@@ -121,7 +121,9 @@ do
 	local _
 	_ = function()
 		local _with_0 = hi
-		return _with_0.a, _with_0.b
+		do
+			return _with_0.a, _with_0.b
+		end
 	end
 end
 do
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 5d031db..c346891 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.25.1"sv;
+const std::string_view version = "0.25.2"sv;
 const std::string_view extension = "yue"sv;
 
 class CompileError : public std::logic_error {
@@ -4490,7 +4490,9 @@ private:
 		for (auto it = nodes.begin(); it != nodes.end(); ++it) {
 			auto node = *it;
 			auto stmt = static_cast<Statement_t*>(node);
-			if (auto pipeBody = stmt->content.as<PipeBody_t>()) {
+			if (!stmt->appendix && stmt->content.is<Return_t>() && stmt != nodes.back()) {
+				throw CompileError("'return' statement must be the last line in the block"sv, stmt->content);
+			} else if (auto pipeBody = stmt->content.as<PipeBody_t>()) {
 				auto x = stmt;
 				bool cond = false;
 				BLOCK_START
@@ -9151,7 +9153,38 @@ private:
 			ifNode->nodes.push_back(with->body);
 			transformIf(ifNode, temp, ExpUsage::Common);
 		} else {
-			transform_plain_body(with->body, temp, ExpUsage::Common);
+			bool transformed = false;
+			if (auto block = with->body.as<Block_t>()) {
+				if (!block->statements.empty()) {
+					Statement_t* stmt = static_cast<Statement_t*>(block->statements.back());
+					if (stmt->content.is<Return_t>()) {
+						auto newBlock = with->body->new_ptr<Block_t>();
+						newBlock->statements.dup(block->statements);
+						newBlock->statements.pop_back();
+						transform_plain_body(newBlock, temp, ExpUsage::Common);
+						auto newBody = stmt->new_ptr<Body_t>();
+						newBody->content.set(stmt);
+						auto doNode = stmt->new_ptr<Do_t>();
+						doNode->body.set(newBody);
+						transformDo(doNode, temp, ExpUsage::Common);
+						transformed = true;
+					}
+				}
+			} else {
+				auto stmt = with->body.to<Statement_t>();
+				if (stmt->content.is<Return_t>()) {
+					auto newBody = stmt->new_ptr<Body_t>();
+					newBody->content.set(stmt);
+					auto doNode = stmt->new_ptr<Do_t>();
+					doNode->body.set(newBody);
+					transformDo(doNode, temp, ExpUsage::Common);
+					temp.back().insert(0, indent());
+					transformed = true;
+				}
+			}
+			if (!transformed) {
+				transform_plain_body(with->body, temp, ExpUsage::Common);
+			}
 		}
 		_withVars.pop();
 		if (assignList) {
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index e5337b0..93787cd 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -369,11 +369,11 @@ YueParser::YueParser() {
 	Switch = key("switch") >> space >> Exp >>
 		space >> Seperator >> (
 			SwitchCase >> space >> (
-				line_break >> *space_break >> check_indent_match >> space >> SwitchCase >> switch_block |
+				switch_block |
 				*(space >> SwitchCase) >> -(space >> switch_else)
 			) |
 			+space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent
-		) >> switch_block;
+		);
 
 	Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> if_assignment_syntax_error);
 	IfCond = disable_chain_rule(disable_arg_table_block_rule(Exp >> -(space >> Assignment)));
-- 
cgit v1.2.3-55-g6feb