From c3a389e2f9f53fb3e3e70a325bf42c8ce02a0b82 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Wed, 10 Feb 2021 23:36:22 +0800 Subject: fix local statement used with line decorator issue. --- src/MoonP/moon_ast.h | 2 ++ src/MoonP/moon_compiler.cpp | 87 +++++++++++++++++++++++++++++++-------------- 2 files changed, 62 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index 2f5123b..e2f54de 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h @@ -110,6 +110,8 @@ AST_NODE(Local) ast_sel item; std::list forceDecls; std::list decls; + bool collected = false; + bool defined = false; AST_MEMBER(Local, &item) AST_END(Local) diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index 2ed153e..6b721f1 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp @@ -53,7 +53,7 @@ inline std::string s(std::string_view sv) { return std::string(sv); } -const std::string_view version = "0.6.1"sv; +const std::string_view version = "0.6.2"sv; const std::string_view extension = "mp"sv; class MoonCompilerImpl { @@ -516,18 +516,29 @@ private: return nullptr; } + Statement_t* lastStatementFrom(const node_container& stmts) const { + if (!stmts.empty()) { + auto it = stmts.end(); --it; + while (!static_cast(*it)->content && it != stmts.begin()) { + --it; + } + return static_cast(*it); + } + return nullptr; + } + Statement_t* lastStatementFrom(Body_t* body) const { if (auto stmt = body->content.as()) { return stmt; } else { const auto& stmts = body->content.to()->statements.objects(); - return stmts.empty() ? nullptr : static_cast(stmts.back()); + return lastStatementFrom(stmts); } } Statement_t* lastStatementFrom(Block_t* block) const { const auto& stmts = block->statements.objects(); - return stmts.empty() ? nullptr : static_cast(stmts.back()); + return lastStatementFrom(stmts); } Exp_t* lastExpFromAssign(ast_node* action) { @@ -773,6 +784,11 @@ private: if (auto assignment = assignmentFrom(statement)) { auto preDefine = getPredefine(assignment); if (!preDefine.empty()) out.push_back(preDefine + nll(statement)); + } else if (auto local = statement->content.as()) { + if (!local->defined) { + local->defined = true; + transformLocalDef(local, out); + } } auto appendix = statement->appendix.get(); switch (appendix->item->getId()) { @@ -2009,6 +2025,13 @@ private: BREAK_IF(it == nodes.begin()); auto last = it; --last; auto lst = static_cast(*last); + if (lst->appendix) { + throw std::logic_error(_info.errorMessage("statement decorator must be placed at the end of backcall chain"sv, lst->appendix.get())); + } + lst->appendix.set(stmt->appendix); + stmt->appendix.set(nullptr); + lst->needSep.set(stmt->needSep); + stmt->needSep.set(nullptr); auto exp = lastExpFromStatement(lst); BREAK_IF(!exp); for (auto val : backcallBody->values.objects()) { @@ -2104,27 +2127,30 @@ private: return; } if (auto local = stmt->content.as()) { - switch (local->item->getId()) { - case id(): { - auto flag = local->item.to(); - LocalMode newMode = _parser.toString(flag) == "*"sv ? LocalMode::Any : LocalMode::Capital; - if (int(newMode) > int(mode)) { - mode = newMode; - } - if (mode == LocalMode::Any) { - if (!any) any = local; - if (!capital) capital = local; - } else { - if (!capital) capital = local; + if (!local->collected) { + local->collected = true; + switch (local->item->getId()) { + case id(): { + auto flag = local->item.to(); + LocalMode newMode = _parser.toString(flag) == "*"sv ? LocalMode::Any : LocalMode::Capital; + if (int(newMode) > int(mode)) { + mode = newMode; + } + if (mode == LocalMode::Any) { + if (!any) any = local; + if (!capital) capital = local; + } else { + if (!capital) capital = local; + } + break; } - break; - } - case id(): { - auto values = local->item.to(); - for (auto name : values->nameList->names.objects()) { - local->forceDecls.push_back(_parser.toString(name)); + case id(): { + auto values = local->item.to(); + for (auto name : values->nameList->names.objects()) { + local->forceDecls.push_back(_parser.toString(name)); + } + break; } - break; } } } else if (mode != LocalMode::None) { @@ -2194,8 +2220,8 @@ private: case ExpUsage::Return: { BLOCK_START BREAK_IF(isRoot && !_info.moduleName.empty()); - BREAK_IF(nodes.empty()); - auto last = static_cast(nodes.back()); + auto last = lastStatementFrom(nodes); + BREAK_IF(!last); auto x = last; auto expList = expListFrom(last); BREAK_IF(!expList || @@ -5434,8 +5460,7 @@ private: out.push_back(join(temp)); } - void transformLocal(Local_t* local, str_list& out) { - str_list temp; + void transformLocalDef(Local_t* local, str_list& out) { if (!local->forceDecls.empty() || !local->decls.empty()) { str_list defs; for (const auto& decl : local->forceDecls) { @@ -5449,9 +5474,17 @@ private: } auto preDefine = getPredefine(defs); if (!preDefine.empty()) { - temp.push_back(preDefine + nll(local)); + out.push_back(preDefine + nll(local)); } } + } + + void transformLocal(Local_t* local, str_list& out) { + str_list temp; + if (!local->defined) { + local->defined = true; + transformLocalDef(local, temp); + } if (auto values = local->item.as()) { if (values->valueList) { auto x = local; -- cgit v1.2.3-55-g6feb