From cd2b60b101a398cb9356d746364e70eaed1860f1 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Mon, 22 Jun 2020 16:50:40 +0800 Subject: add support for local variable declared with attribute 'close' and 'const' for Lua 5.4. --- src/MoonP/moon_ast.h | 11 ++++++++- src/MoonP/moon_compiler.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++-- src/MoonP/moon_parser.cpp | 11 ++++++++- src/MoonP/moon_parser.h | 1 + src/MoonP/stacktraceplus.h | 4 +-- 5 files changed, 80 insertions(+), 6 deletions(-) (limited to 'src/MoonP') diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index 42522dd..1491344 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h @@ -113,6 +113,15 @@ AST_NODE(Local) AST_MEMBER(Local, &item) AST_END(Local) +class Assign_t; + +AST_NODE(LocalAttrib) + ast_ptr attrib; + ast_ptr nameList; + ast_ptr assign; + AST_MEMBER(LocalAttrib, &attrib, &nameList, &assign) +AST_END(LocalAttrib) + AST_NODE(colon_import_name) ast_ptr name; AST_MEMBER(colon_import_name, &name) @@ -686,7 +695,7 @@ AST_END(statement_sep) AST_NODE(Statement) ast_sel content; + Label_t, Goto_t, Backcall_t, LocalAttrib_t, ExpListAssign_t> content; ast_ptr appendix; ast_ptr needSep; AST_MEMBER(Statement, &content, &appendix, &needSep) diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index f7462dc..8dc5c94 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp @@ -25,6 +25,12 @@ extern "C" { } // extern "C" +#if LUA_VERSION_NUM > 501 + #ifndef LUA_COMPAT_5_1 + #define lua_objlen lua_rawlen + #endif // LUA_COMPAT_5_1 +#endif // LUA_VERSION_NUM + namespace MoonP { using namespace std::string_view_literals; using namespace parserlib; @@ -43,7 +49,7 @@ inline std::string s(std::string_view sv) { } const std::string_view version() { - return "0.4.0"sv; + return "0.4.1"sv; } // name of table stored in lua registry @@ -769,6 +775,7 @@ private: case id(): transformBreakLoop(static_cast(content), out); break; case id(): transformLabel(static_cast(content), out); break; case id(): transformGoto(static_cast(content), out); break; + case id(): transformLocalAttrib(static_cast(content), out); break; case id(): { auto expListAssign = static_cast(content); if (expListAssign->action) { @@ -2071,7 +2078,18 @@ private: last->needSep.set(nullptr); auto bLast = ++nodes.rbegin(); if (bLast != nodes.rend()) { - static_cast(*bLast)->needSep.set(nullptr); + bool isMacro = false; + BLOCK_START + BREAK_IF(expListLow->exprs.size() != 1); + auto exp = static_cast(expListLow->exprs.back()); + BREAK_IF(!exp->opValues.empty()); + auto chainValue = exp->getByPath(); + BREAK_IF(!chainValue); + isMacro = isMacroChain(chainValue); + BLOCK_END + if (!isMacro) { + ast_to(*bLast)->needSep.set(nullptr); + } } BLOCK_END break; @@ -5099,6 +5117,43 @@ private: out.push_back(join(temp)); } + void transformLocalAttrib(LocalAttrib_t* localAttrib, str_list& out) { + auto x = localAttrib; + auto attrib = _parser.toString(localAttrib->attrib); + if (attrib != "close"sv && attrib != "const"sv) { + throw std::logic_error(_info.errorMessage(s("unknown attribute '"sv) + attrib + '\'', localAttrib->attrib)); + } + auto expList = x->new_ptr(); + str_list tmpVars; + str_list vars; + for (auto name : localAttrib->nameList->names.objects()) { + auto callable = x->new_ptr(); + callable->item.set(name); + auto chainValue = x->new_ptr(); + chainValue->items.push_back(callable); + auto value = x->new_ptr(); + value->item.set(chainValue); + auto exp = newExp(value, x); + expList->exprs.push_back(exp); + tmpVars.push_back(getUnusedName("_var_"sv)); + vars.push_back(_parser.toString(name)); + } + auto tmpVarStr = join(tmpVars, ","sv); + auto tmpVarList = toAst(tmpVarStr, x); + auto assignment = x->new_ptr(); + assignment->expList.set(tmpVarList); + assignment->action.set(localAttrib->assign); + str_list temp; + transformAssignment(assignment, temp); + attrib = s(" <"sv) + attrib + '>'; + for (auto& var : vars) { + forceAddToScope(var); + var.append(attrib); + } + temp.push_back(indent() + s("local "sv) + join(vars) + s(" = "sv) + tmpVarStr + nll(x)); + out.push_back(join(temp)); + } + void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { auto keyword = _parser.toString(breakLoop); if (keyword == "break"sv) { diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index 25e67b3..4dee5b1 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp @@ -174,6 +174,14 @@ MoonParser::MoonParser() { local_values = NameList >> -(sym('=') >> (TableBlock | ExpListLow)); Local = key("local") >> (Space >> local_flag | local_values); + LocalAttrib = and_(key(pl::user(Name, [](const item_t& item) { + State* st = reinterpret_cast(item.user_data); + for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast(*it); + auto it = Keywords.find(st->buffer); + st->buffer.clear(); + return it == Keywords.end(); + })) >> NameList >> sym('=') >> not_('=')) >> Space >> Name >> NameList >> Assign; + colon_import_name = sym('\\') >> Space >> Variable; ImportName = colon_import_name | Space >> Variable; ImportNameList = Seperator >> *SpaceBreak >> ImportName >> *((+SpaceBreak | sym(',') >> *SpaceBreak) >> ImportName); @@ -552,7 +560,8 @@ MoonParser::MoonParser() { Statement = ( Import | While | Repeat | For | ForEach | Return | Local | Global | Export | Macro | - Space >> BreakLoop | Label | Goto | Backcall | ExpListAssign + Space >> BreakLoop | Label | Goto | Backcall | + LocalAttrib | ExpListAssign ) >> Space >> -statement_appendix >> -statement_sep; diff --git a/src/MoonP/moon_parser.h b/src/MoonP/moon_parser.h index 5787438..c6a03f8 100644 --- a/src/MoonP/moon_parser.h +++ b/src/MoonP/moon_parser.h @@ -199,6 +199,7 @@ private: AST_RULE(local_flag) AST_RULE(local_values) AST_RULE(Local) + AST_RULE(LocalAttrib); AST_RULE(colon_import_name) AST_RULE(import_literal_inner) AST_RULE(ImportLiteral) diff --git a/src/MoonP/stacktraceplus.h b/src/MoonP/stacktraceplus.h index 3d32322..d658c5c 100644 --- a/src/MoonP/stacktraceplus.h +++ b/src/MoonP/stacktraceplus.h @@ -406,8 +406,8 @@ function _M.stacktrace(thread, message, level) end end if fname then - fname = fname:gsub("%[string \"", "") - fname = fname:gsub("\"%]", "") + local fn = fname:match("%[string \"(.-)\"%]") + if fn then fname = fn end fname = fname:gsub("^%s*(.-)%s*$", "%1") fname, line = getMoonLineNumber(fname, line) if _M.simplified then -- cgit v1.2.3-55-g6feb