From 6402a8896c78440aee03cc4b7bb315fc236e6ff8 Mon Sep 17 00:00:00 2001
From: Li Jin <dragon-fly@qq.com>
Date: Sat, 2 May 2020 14:41:40 +0800
Subject: fix Moonscript issue 416: ambiguous Lua output in some cases.

---
 src/MoonP/moon_ast.h        | 10 +++++++---
 src/MoonP/moon_compiler.cpp | 35 +++++++++++++++++++++++++++++++++--
 src/MoonP/moon_parser.cpp   |  3 ++-
 src/MoonP/moon_parser.h     |  3 ++-
 4 files changed, 44 insertions(+), 7 deletions(-)

(limited to 'src')

diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h
index dd11ac4..4918a0a 100644
--- a/src/MoonP/moon_ast.h
+++ b/src/MoonP/moon_ast.h
@@ -663,20 +663,24 @@ AST_NODE(unless_line)
 	AST_MEMBER(unless_line, &condition)
 AST_END(unless_line)
 
+AST_LEAF(BreakLoop)
+AST_END(BreakLoop)
+
 AST_NODE(statement_appendix)
 	ast_sel<true, if_line_t, unless_line_t, CompInner_t> item;
 	AST_MEMBER(statement_appendix, &item)
 AST_END(statement_appendix)
 
-AST_LEAF(BreakLoop)
-AST_END(BreakLoop)
+AST_LEAF(statement_sep)
+AST_END(statement_sep)
 
 AST_NODE(Statement)
 	ast_sel<true, Import_t, While_t, Repeat_t, For_t, ForEach_t,
 		Return_t, Local_t, Global_t, Export_t, Macro_t, BreakLoop_t,
 		Label_t, Goto_t, Backcall_t, ExpListAssign_t> content;
 	ast_ptr<false, statement_appendix_t> appendix;
-	AST_MEMBER(Statement, &content, &appendix)
+	ast_ptr<false, statement_sep_t> needSep;
+	AST_MEMBER(Statement, &content, &appendix, &needSep)
 AST_END(Statement)
 
 class Block_t;
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp
index f79df07..6d07e9e 100644
--- a/src/MoonP/moon_compiler.cpp
+++ b/src/MoonP/moon_compiler.cpp
@@ -43,7 +43,7 @@ inline std::string s(std::string_view sv) {
 }
 
 const std::string_view version() {
-	return "0.3.11"sv;
+	return "0.3.12"sv;
 }
 
 // name of table stored in lua registry
@@ -802,6 +802,25 @@ private:
 			}
 			default: assert(false); break;
 		}
+		if (statement->needSep && !out.back().empty()) {
+			auto index = std::string::npos;
+			if (_config.reserveLineNumber) {
+				index = out.back().rfind(" -- "sv);
+			} else {
+				index = out.back().find_last_not_of('\n');
+				if (index != std::string::npos) index++;
+			}
+			if (index != std::string::npos) {
+				auto ending = out.back().substr(0, index);
+				auto ind = ending.find_last_of(" \t\n"sv);
+				if (ind != std::string::npos) {
+					ending = ending.substr(ind + 1);
+				}
+				if (Keywords.find(ending) == Keywords.end()) {
+					out.back().insert(index, ";"sv);
+				}
+			}
+		}
 	}
 
 	str_list getAssignVars(ExpListAssign_t* assignment) {
@@ -2016,6 +2035,11 @@ private:
 				returnNode->valueList.set(expListLow);
 				returnNode->allowBlockMacroReturn = true;
 				last->content.set(returnNode);
+				last->needSep.set(nullptr);
+				auto bLast = ++nodes.rbegin();
+				if (bLast != nodes.rend()) {
+					static_cast<Statement_t*>(*bLast)->needSep.set(nullptr);
+				}
 				BLOCK_END
 				break;
 			}
@@ -2041,6 +2065,11 @@ private:
 					}
 					newAssignment->action.set(assign);
 					last->content.set(newAssignment);
+					last->needSep.set(nullptr);
+					auto bLast = ++nodes.rbegin();
+					if (bLast != nodes.rend()) {
+						static_cast<Statement_t*>(*bLast)->needSep.set(nullptr);
+					}
 				}
 				break;
 			}
@@ -4029,7 +4058,9 @@ private:
 		_buf << indent(1) << "end"sv << nll(classDecl);
 		_buf << indent() << "})"sv << nll(classDecl);
 		_buf << indent() << baseVar << ".__class = "sv << classVar << nll(classDecl);
-		if (!statements.empty()) _buf << indent() << "local self = "sv << classVar << nll(classDecl);
+		if (!statements.empty()) {
+			_buf << indent() << "local self = "sv << classVar << ';' << nll(classDecl);
+		}
 		_buf << join(statements);
 		if (extend) {
 			_buf << indent() << "if "sv << parentVar << ".__inherited then"sv << nll(classDecl);
diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp
index 4f12a34..5b537a1 100644
--- a/src/MoonP/moon_parser.cpp
+++ b/src/MoonP/moon_parser.cpp
@@ -538,12 +538,13 @@ MoonParser::MoonParser() {
 	unless_line = key("unless") >> Exp;
 
 	statement_appendix = (if_line | unless_line | CompInner) >> Space;
+	statement_sep = and_(*SpaceBreak >> CheckIndent >> Space >> (set("($'\"") | expr("[[") | expr("[=")));
 	Statement = (
 		Import | While | Repeat | For | ForEach |
 		Return | Local | Global | Export | Macro |
 		Space >> BreakLoop | Label | Goto | Backcall | ExpListAssign
 	) >> Space >>
-	-statement_appendix;
+	-statement_appendix >> -statement_sep;
 
 	Body = Space >> Break >> *EmptyLine >> InBlock | Statement;
 
diff --git a/src/MoonP/moon_parser.h b/src/MoonP/moon_parser.h
index 1f9caf8..00bbcd5 100644
--- a/src/MoonP/moon_parser.h
+++ b/src/MoonP/moon_parser.h
@@ -289,8 +289,9 @@ private:
 	AST_RULE(ExpListAssign)
 	AST_RULE(if_line)
 	AST_RULE(unless_line)
-	AST_RULE(statement_appendix)
 	AST_RULE(BreakLoop)
+	AST_RULE(statement_appendix)
+	AST_RULE(statement_sep)
 	AST_RULE(Statement)
 	AST_RULE(Body)
 	AST_RULE(Block)
-- 
cgit v1.2.3-55-g6feb