From 890fc913737c62c5d7e51636e0535b7b318a0d89 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Thu, 5 Mar 2020 16:08:41 +0800 Subject: move functions of old export statement to global statement, make export statement work with Lua module system. --- .gitignore | 2 + MoonPlus.sln | 31 +++++++ MoonPlus.vcxproj | 173 ++++++++++++++++++++++++++++++++++++ MoonPlus.vcxproj.filters | 46 ++++++++++ MoonPlus.vcxproj.user | 4 + spec/inputs/class.moon | 2 +- spec/inputs/export.moon | 98 +++++++------------- spec/inputs/export_default.moon | 15 ++++ spec/inputs/global.moon | 77 ++++++++++++++++ spec/inputs/import.moon | 2 +- src/MoonP/moon_ast.h | 26 ++++-- src/MoonP/moon_compiler.cpp | 192 ++++++++++++++++++++++++++++++++-------- src/MoonP/moon_parser.cpp | 74 ++++++++++------ src/MoonP/moon_parser.h | 19 ++-- src/moonp.cpp | 6 +- 15 files changed, 623 insertions(+), 144 deletions(-) create mode 100644 MoonPlus.sln create mode 100644 MoonPlus.vcxproj create mode 100644 MoonPlus.vcxproj.filters create mode 100644 MoonPlus.vcxproj.user create mode 100644 spec/inputs/export_default.moon create mode 100644 spec/inputs/global.moon diff --git a/.gitignore b/.gitignore index 27acefe..5994846 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ build.luarocks spec/outputs moonplus-*.rock* !moonplus-dev-1.rockspec +.vs +bin diff --git a/MoonPlus.sln b/MoonPlus.sln new file mode 100644 index 0000000..252e9b4 --- /dev/null +++ b/MoonPlus.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29806.167 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MoonPlus", "MoonPlus.vcxproj", "{CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Debug|x64.ActiveCfg = Debug|x64 + {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Debug|x64.Build.0 = Debug|x64 + {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Debug|x86.ActiveCfg = Debug|Win32 + {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Debug|x86.Build.0 = Debug|Win32 + {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Release|x64.ActiveCfg = Release|x64 + {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Release|x64.Build.0 = Release|x64 + {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Release|x86.ActiveCfg = Release|Win32 + {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {49826A7F-7A92-4CFC-95DD-28B7045BB2F7} + EndGlobalSection +EndGlobal diff --git a/MoonPlus.vcxproj b/MoonPlus.vcxproj new file mode 100644 index 0000000..fd502ab --- /dev/null +++ b/MoonPlus.vcxproj @@ -0,0 +1,173 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD} + MoonPlus + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\build\windows\$(Configuration)\ + $(SolutionDir)\bin\windows\$(Configuration)\ + + + true + $(SolutionDir)\bin\windows\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\windows\$(Platform)\$(Configuration)\ + + + false + $(SolutionDir)\build\windows\$(Configuration)\ + $(SolutionDir)\bin\windows\$(Configuration)\ + + + false + $(SolutionDir)\bin\windows\$(Platform)\$(Configuration)\ + $(SolutionDir)\build\windows\$(Platform)\$(Configuration)\ + + + + Level3 + true + _DEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions) + true + stdcpplatest + .\src;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + true + _DEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions) + true + stdcpplatest + .\src;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions) + true + stdcpplatest + .\src;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions) + true + stdcpplatest + .\src;%(AdditionalIncludeDirectories) + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MoonPlus.vcxproj.filters b/MoonPlus.vcxproj.filters new file mode 100644 index 0000000..6550779 --- /dev/null +++ b/MoonPlus.vcxproj.filters @@ -0,0 +1,46 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {c88639d5-457d-42eb-b852-65682c89c618} + + + + + src\MoonP + + + src\MoonP + + + src\MoonP + + + src\MoonP + + + src + + + + + src\MoonP + + + src\MoonP + + + src\MoonP + + + src\MoonP + + + src\MoonP + + + \ No newline at end of file diff --git a/MoonPlus.vcxproj.user b/MoonPlus.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/MoonPlus.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/spec/inputs/class.moon b/spec/inputs/class.moon index 3288dc6..533694e 100644 --- a/spec/inputs/class.moon +++ b/spec/inputs/class.moon @@ -158,7 +158,7 @@ print (class WhatsUp).__name -- -export ^ +global ^ class Something _ = nil diff --git a/spec/inputs/export.moon b/spec/inputs/export.moon index a8c782c..9c906d5 100644 --- a/spec/inputs/export.moon +++ b/spec/inputs/export.moon @@ -1,77 +1,45 @@ -do - export a,b,c = 223, 343 - export cool = "dad" +export a,b,c = 223, 343, 123 +export cool = "dad" -do - export class Something - umm: "cool" +d,e,f = 3, 2, 1 +export d, e, f -do - export a,b,c - a,b,c,d = "hello" +export class Something + umm: "cool" +export if this + 232 +else + 4343 -do - What = if this - 232 - else - 4343 +export What = if this + 232 +else + 4343 - export ^ +export y = -> + hallo = 3434 - another = 3434 - Another = 7890 +export with tmp + j = 2000 - if inner then Yeah = "10000" - - What = if this - 232 - else - 4343 - - -do - export * - - What = if this - 232 - else - 4343 - - x,y,z = 1,2,3 - - y = -> - hallo = 3434 - - with tmp - j = 2000 - - -do - export * - x = 3434 - if y then - x = 10 - -do - export * - if y then - x = 10 - x = 3434 - -do - do - export * - - k = 1212 +export cbVal = do + h = 100 + (x)<- f + return x h - do - h = 100 +export y = -> + h = 100 + k = 100 - y = -> - h = 100 - k = 100 +export switch h + when 100, 150 then 200 + when 200 then 300 + else 0 - h = 100 +export Constant = switch value + when "good" then 1 + when "better" then 2 + when "best" then 3 diff --git a/spec/inputs/export_default.moon b/spec/inputs/export_default.moon new file mode 100644 index 0000000..73f43ac --- /dev/null +++ b/spec/inputs/export_default.moon @@ -0,0 +1,15 @@ + +print "OK" + +export default -> + print "hello" + 123 + +(x, fy)<- f 123, "abc" unless isOff +print x +(y, res)<- fy +return if res + abc + y +else + abc + diff --git a/spec/inputs/global.moon b/spec/inputs/global.moon new file mode 100644 index 0000000..7d6cfde --- /dev/null +++ b/spec/inputs/global.moon @@ -0,0 +1,77 @@ + +do + global a,b,c = 223, 343 + global cool = "dad" + +do + global class Something + umm: "cool" + +do + global a,b,c + a,b,c,d = "hello" + + +do + What = if this + 232 + else + 4343 + + global ^ + + another = 3434 + Another = 7890 + + if inner then Yeah = "10000" + + What = if this + 232 + else + 4343 + + +do + global * + + What = if this + 232 + else + 4343 + + x,y,z = 1,2,3 + + y = -> + hallo = 3434 + + with tmp + j = 2000 + + +do + global * + x = 3434 + if y then + x = 10 + +do + global * + if y then + x = 10 + x = 3434 + +do + do + global * + + k = 1212 + + do + h = 100 + + y = -> + h = 100 + k = 100 + + h = 100 + diff --git a/spec/inputs/import.moon b/spec/inputs/import.moon index ded1ffd..99981f8 100644 --- a/spec/inputs/import.moon +++ b/spec/inputs/import.moon @@ -58,7 +58,7 @@ do import "lpeg" as {:C, :Ct, :Cmt} do - export * + global * import 'module' import 'module_x' import "org.package.module-y" diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index dd01165..9fab215 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h @@ -500,18 +500,28 @@ AST_NODE(ClassDecl) AST_MEMBER(ClassDecl, &name, &extend, &body) AST_END(ClassDecl) -AST_NODE(export_values) +AST_NODE(global_values) ast_ptr nameList; ast_ptr valueList; - AST_MEMBER(export_values, &nameList, &valueList) -AST_END(export_values) + AST_MEMBER(global_values, &nameList, &valueList) +AST_END(global_values) -AST_LEAF(export_op) -AST_END(export_op) +AST_LEAF(global_op) +AST_END(global_op) + +AST_NODE(Global) + ast_sel item; + AST_MEMBER(Global, &item) +AST_END(Global) + +AST_LEAF(export_default) +AST_END(export_default) AST_NODE(Export) - ast_sel item; - AST_MEMBER(Export, &item) + ast_ptr def; + ast_sel target; + ast_ptr assign; + AST_MEMBER(Export, &def, &target, &assign) AST_END(Export) AST_NODE(FnArgDef) @@ -601,7 +611,7 @@ AST_END(BreakLoop) AST_NODE(Statement) ast_sel content; ast_ptr appendix; AST_MEMBER(Statement, &content, &appendix) diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index 83b91e6..1adfec9 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp @@ -32,7 +32,7 @@ inline std::string s(std::string_view sv) { } const char* moonScriptVersion() { - return "0.5.0-r0.1.5"; + return "0.5.0-r0.2.0"; } class MoonCompilerImpl { @@ -45,7 +45,10 @@ public: try { str_list out; pushScope(); - transformBlock(_info.node.to()->block, out, config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common); + enableReturn.push(_info.moduleName.empty()); + transformBlock(_info.node.to()->block, out, + config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common, + nullptr, true); popScope(); if (config.lintGlobalVariable) { globals = std::make_unique>(); @@ -86,6 +89,7 @@ private: MoonParser _parser; ParseInfo _info; int _indentOffset = 0; + std::stack enableReturn; std::list> _codeCache; std::stack _withVars; std::stack _continueVars; @@ -98,16 +102,16 @@ private: Capital = 1, Any = 2 }; - enum class ExportMode { + enum class GlobalMode { None = 0, Capital = 1, Any = 2 }; struct Scope { - ExportMode mode = ExportMode::None; + GlobalMode mode = GlobalMode::None; std::unique_ptr> vars; std::unique_ptr> allows; - std::unique_ptr> exports; + std::unique_ptr> globals; }; std::list _scopes; static const std::string Empty; @@ -153,11 +157,11 @@ private: bool isDefined(const std::string& name) const { bool isDefined = false; - int mode = int(std::isupper(name[0]) ? ExportMode::Capital : ExportMode::Any); + int mode = int(std::isupper(name[0]) ? GlobalMode::Capital : GlobalMode::Any); const auto& current = _scopes.back(); if (int(current.mode) >= mode) { - if (current.exports) { - if (current.exports->find(name) != current.exports->end()) { + if (current.globals) { + if (current.globals->find(name) != current.globals->end()) { isDefined = true; current.vars->insert(name); } @@ -202,17 +206,17 @@ private: scope.allows = std::make_unique>(); } - void markVarExported(ExportMode mode, bool specified) { + void markVarGlobal(GlobalMode mode, bool specified) { auto& scope = _scopes.back(); scope.mode = mode; - if (specified && !scope.exports) { - scope.exports = std::make_unique>(); + if (specified && !scope.globals) { + scope.globals = std::make_unique>(); } } - void addExportedVar(const std::string& name) { + void addGlobalVar(const std::string& name) { auto& scope = _scopes.back(); - scope.exports->insert(name); + scope.globals->insert(name); } void addToAllowList(const std::string& name) { @@ -457,6 +461,20 @@ private: return Empty; } + Variable_t* variableFrom(Exp_t* exp) { + BLOCK_START + auto value = singleValueFrom(exp); + BREAK_IF(!value); + auto chainValue = value->getByPath(); + BREAK_IF(!chainValue); + BREAK_IF(chainValue->items.size() != 1); + auto callable = ast_cast(chainValue->items.front()); + BREAK_IF(!callable); + return callable->item.as(); + BLOCK_END + return nullptr; + } + bool isAssignable(const node_container& chainItems) const { if (chainItems.size() == 1) { auto firstItem = chainItems.back(); @@ -647,6 +665,7 @@ private: case id(): transformForEach(static_cast(content), out); break; case id(): transformReturn(static_cast(content), out); break; case id(): transformLocal(static_cast(content), out); break; + case id(): transformGlobal(static_cast(content), out); break; case id(): transformExport(static_cast(content), out); break; case id(): transformBreakLoop(static_cast(content), out); break; case id(): { @@ -693,7 +712,7 @@ private: break; } } - throw std::logic_error(_info.errorMessage("Expression list must appear at the end of body or block."sv, expList)); + throw std::logic_error(_info.errorMessage("Expression list is not supported here."sv, expList)); } break; } @@ -749,8 +768,8 @@ private: return preDefs; } - str_list transformAssignDefs(ExpList_t* expList) { - str_list preDefs; + str_list transformAssignDefs(ExpList_t* expList, bool markDefined = true) { + str_list defs; for (auto exp_ : expList->exprs.objects()) { auto exp = static_cast(exp_); if (auto value = singleValueFrom(exp)) { @@ -766,8 +785,8 @@ private: if (self->name.is()) name = "self"sv; } BREAK_IF(name.empty()); - if (addToScope(name)) { - preDefs.push_back(name); + if (!markDefined || addToScope(name)) { + defs.push_back(name); } BLOCK_END } @@ -775,7 +794,7 @@ private: throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp)); } } - return preDefs; + return defs; } std::string getPredefine(const str_list& defs) { @@ -1650,6 +1669,7 @@ private: } void transformFunLit(FunLit_t* funLit, str_list& out) { + enableReturn.push(true); str_list temp; bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv; pushScope(); @@ -1698,6 +1718,7 @@ private: } } out.push_back(clearBuf()); + enableReturn.pop(); } void transformBody(Body_t* body, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { @@ -1711,7 +1732,7 @@ private: } } - void transformBlock(Block_t* block, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { + void transformBlock(Block_t* block, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool isRoot = false) { const auto& nodes = block->statements.objects(); LocalMode mode = LocalMode::None; Local_t* any = nullptr, *capital = nullptr; @@ -1768,7 +1789,7 @@ private: args->swap(a, arg); findPlaceHolder = true; } else { - throw std::logic_error(_info.errorMessage("backcall placeholder can be used only in one place."sv, a)); + throw std::logic_error(_info.errorMessage("Backcall placeholder can be used only in one place."sv, a)); } } } @@ -1792,9 +1813,10 @@ private: auto expListAssign = x->new_ptr(); expListAssign->expList.set(expList); newStmt->content.set(expListAssign); + newStmt->appendix.set(stmt->appendix); newBlock->statements.push_back(newStmt); } - transformBlock(newBlock, out, usage, assignList); + transformBlock(newBlock, out, usage, assignList, isRoot); return; } if (auto local = stmt->content.as()) { @@ -1838,6 +1860,15 @@ private: } } } + if (info.second) { + auto defs = transformAssignDefs(info.second->expList, false); + for (const auto& def : defs) { + if (std::isupper(def[0]) && capital) { capital->decls.push_back(def); + } else if (any) { + any->decls.push_back(def); + } + } + } BLOCK_START auto assign = assignment->action.as(); BREAK_IF(!assign); @@ -1865,10 +1896,14 @@ private: } } } + if (isRoot && !_info.moduleName.empty()) { + block->statements.push_front(toAst(_info.moduleName + s(_info.exportDefault ? "=nil"sv : "={}"sv), block)); + } switch (usage) { case ExpUsage::Closure: case ExpUsage::Return: { BLOCK_START + BREAK_IF(isRoot && !_info.moduleName.empty()); BREAK_IF(nodes.empty()); auto last = static_cast(nodes.back()); auto x = last; @@ -1920,9 +1955,17 @@ private: } else { out.push_back(Empty); } + if (isRoot && !_info.moduleName.empty()) { + out.back().append(indent() + s("return "sv) + _info.moduleName + nlr(block)); + } } void transformReturn(Return_t* returnNode, str_list& out) { + if (!enableReturn.top()) { + ast_node* target = returnNode->valueList.get(); + if (!target) target = returnNode; + throw std::logic_error(_info.errorMessage("Illegal return statement here."sv, target)); + } if (auto valueList = returnNode->valueList.get()) { if (valueList->exprs.size() == 1) { auto exp = static_cast(valueList->exprs.back()); @@ -3797,33 +3840,33 @@ private: out.push_back(_parser.toString(const_value)); } - void transformExport(Export_t* exportNode, str_list& out) { - auto x = exportNode; - auto item = exportNode->item.get(); + void transformGlobal(Global_t* global, str_list& out) { + auto x = global; + auto item = global->item.get(); switch (item->getId()) { case id(): { auto classDecl = static_cast(item); if (classDecl->name && classDecl->name->item->getId() == id()) { - markVarExported(ExportMode::Any, true); - addExportedVar(_parser.toString(classDecl->name->item)); + markVarGlobal(GlobalMode::Any, true); + addGlobalVar(_parser.toString(classDecl->name->item)); } transformClassDecl(classDecl, out, ExpUsage::Common); break; } - case id(): + case id(): if (_parser.toString(item) == "*"sv) { - markVarExported(ExportMode::Any, false); + markVarGlobal(GlobalMode::Any, false); } else { - markVarExported(ExportMode::Capital, false); + markVarGlobal(GlobalMode::Capital, false); } break; - case id(): { - markVarExported(ExportMode::Any, true); - auto values = exportNode->item.to(); + case id(): { + markVarGlobal(GlobalMode::Any, true); + auto values = global->item.to(); if (values->valueList) { auto expList = x->new_ptr(); for (auto name : values->nameList->names.objects()) { - addExportedVar(_parser.toString(name)); + addGlobalVar(_parser.toString(name)); auto callable = x->new_ptr(); callable->item.set(name); auto chainValue = x->new_ptr(); @@ -3842,7 +3885,7 @@ private: transformAssignment(assignment, out); } else { for (auto name : values->nameList->names.objects()) { - addExportedVar(_parser.toString(name)); + addGlobalVar(_parser.toString(name)); } } break; @@ -3851,6 +3894,85 @@ private: } } + void transformExport(Export_t* exportNode, str_list& out) { + auto x = exportNode; + if (_scopes.size() > 1) { + throw std::logic_error(_info.errorMessage("Can not do module export outside root block."sv, x)); + } + if (exportNode->assign) { + auto expList = exportNode->target.to(); + if (expList->exprs.size() != exportNode->assign->values.size()) { + throw std::logic_error(_info.errorMessage("Left and right expressions must be matched in export statement."sv, x)); + } + for (auto _exp : expList->exprs.objects()) { + auto exp = static_cast(_exp); + if (!variableFrom(exp) && + !exp->getByPath() && + !exp->getByPath()) { + throw std::logic_error(_info.errorMessage("Left hand expressions must be variables in export statement."sv, x)); + } + } + auto assignment = x->new_ptr(); + assignment->expList.set(expList); + assignment->action.set(exportNode->assign); + transformAssignment(assignment, out); + str_list names = transformAssignDefs(expList, false); + auto info = extractDestructureInfo(assignment, true); + if (!info.first.empty()) { + for (const auto& destruct : info.first) + for (const auto& item : destruct.items) + if (item.isVariable) + names.push_back(item.name); + } + if (_info.exportDefault) { + out.back().append(indent() + _info.moduleName + s(" = "sv) + names.back() + nlr(exportNode)); + } else { + str_list lefts, rights; + for (const auto& name : names) { + lefts.push_back(_info.moduleName + s("[\""sv) + name + s("\"]"sv)); + rights.push_back(name); + } + out.back().append(indent() + join(lefts,", "sv) + s(" = "sv) + join(rights, ", "sv) + nlr(exportNode)); + } + } else { + if (_info.exportDefault) { + auto exp = exportNode->target.to(); + auto assignment = x->new_ptr(); + assignment->expList.set(toAst(_info.moduleName, x)); + auto assign = x->new_ptr(); + assign->values.push_back(exp); + assignment->action.set(assign); + transformAssignment(assignment, out); + } else { + str_list temp; + auto expList = exportNode->target.to(); + auto assignment = x->new_ptr(); + auto assignList = toAst(_info.moduleName + s("[#"sv) + _info.moduleName + s("+1]"sv), x); + assignment->expList.set(assignList); + for (auto exp : expList->exprs.objects()) { + if (auto classDecl = exp->getByPath()) { + if (classDecl->name && classDecl->name->item->getId() == id()) { + transformClassDecl(classDecl, temp, ExpUsage::Common); + auto name = _parser.toString(classDecl->name->item); + assignment->expList.set(toAst(_info.moduleName + s("[\""sv) + name + s("\"]"sv), x)); + auto assign = x->new_ptr(); + assign->values.push_back(toAst(name, x)); + assignment->action.set(assign); + transformAssignment(assignment, temp); + assignment->expList.set(assignList); + continue; + } + } + auto assign = x->new_ptr(); + assign->values.push_back(exp); + assignment->action.set(assign); + transformAssignment(assignment, temp); + } + out.push_back(join(temp)); + } + } + } + void transformTable(ast_node* table, const node_container& pairs, str_list& out) { if (pairs.empty()) { out.push_back(s("{ }"sv)); diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index fecf869..baa8eff 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp @@ -28,8 +28,8 @@ std::unordered_set Keywords = { "repeat", "return", "then", "true", "until", "while", // Lua keywords "as", "class", "continue", "export", "extends", - "from", "import", "switch", "unless", "using", - "when", "with" // Moon keywords + "from", "global", "import", "switch", "unless", + "using", "when", "with" // Moon keywords }; MoonParser::MoonParser() { @@ -74,9 +74,15 @@ MoonParser::MoonParser() { Variable = 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); + auto isValid = Keywords.find(st->buffer) == Keywords.end(); + if (isValid) { + if (st->buffer == st->moduleName) { + st->moduleFix++; + st->moduleName = std::string("_module_"sv) + std::to_string(st->moduleFix); + } + } st->buffer.clear(); - return it == Keywords.end(); + return isValid; }); LuaKeyword = pl::user(Name, [](const item_t& item) { @@ -153,7 +159,7 @@ MoonParser::MoonParser() { return true; }); - InBlock = Advance >> Block >> PopIndent; + InBlock = Advance >> ensure(Block, PopIndent); local_flag = expr('*') | expr('^'); Local = key("local") >> ((Space >> local_flag) | NameList); @@ -211,21 +217,18 @@ MoonParser::MoonParser() { DisableDo >> ensure(for_in, PopDo) >> -key("do") >> Body; - Do = pl::user(key("do") >> Body, [](const item_t& item) - { + Do = pl::user(key("do"), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); return st->doStack.empty() || st->doStack.top(); - }); + }) >> Body; - DisableDo = pl::user(true_(), [](const item_t& item) - { + DisableDo = pl::user(true_(), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); st->doStack.push(false); return true; }); - PopDo = pl::user(true_(), [](const item_t& item) - { + PopDo = pl::user(true_(), [](const item_t& item) { State* st = reinterpret_cast(item.user_data); st->doStack.pop(); return true; @@ -312,11 +315,7 @@ MoonParser::MoonParser() { LuaStringContent = *(not_(LuaStringClose) >> Any); - LuaString = pl::user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) { - State* st = reinterpret_cast(item.user_data); - st->stringOpen = -1; - return true; - }); + LuaString = LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose; Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); Callable = Space >> Variable | SelfName | VarArg | Parens; @@ -392,9 +391,30 @@ MoonParser::MoonParser() { -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> -ClassBlock; - export_values = NameList >> -(sym('=') >> ExpListLow); - export_op = expr('*') | expr('^'); - Export = key("export") >> (ClassDecl | (Space >> export_op) | export_values); + global_values = NameList >> -(sym('=') >> ExpListLow); + global_op = expr('*') | expr('^'); + Global = key("global") >> (ClassDecl | (Space >> global_op) | global_values); + + export_default = key("default"); + + Export = pl::user(key("export"), [](const item_t& item) { + State* st = reinterpret_cast(item.user_data); + st->exportCount++; + return true; + }) >> ((pl::user(export_default, [](const item_t& item) { + State* st = reinterpret_cast(item.user_data); + bool isValid = !st->exportDefault && st->exportCount == 1; + st->exportDefault = true; + return isValid; + }) >> Exp) + | (pl::user(true_(), [](const item_t& item) { + State* st = reinterpret_cast(item.user_data); + if (st->exportDefault && st->exportCount > 1) { + return false; + } else { + return true; + } + }) >> ExpList >> -Assign)) >> not_(Space >> statement_appendix); variable_pair = sym(':') >> Variable; @@ -479,12 +499,12 @@ MoonParser::MoonParser() { statement_appendix = (if_else_line | unless_line | CompInner) >> Space; Statement = ( Import | While | For | ForEach | - Return | Local | Export | Space >> BreakLoop | + Return | Local | Global | Export | Space >> BreakLoop | Backcall | ExpListAssign ) >> Space >> -statement_appendix; - Body = -Space >> Break >> *EmptyLine >> InBlock | Statement; + Body = Space >> Break >> *EmptyLine >> InBlock | Statement; empty_line_stop = Space >> and_(Stop); Line = CheckIndent >> Statement | empty_line_stop; @@ -498,7 +518,7 @@ ParseInfo MoonParser::parse(std::string_view codes, rule& r) { ParseInfo res; try { res.codes = std::make_unique(); - *(res.codes) = _converter.from_bytes(codes.begin(), codes.end()); + *(res.codes) = _converter.from_bytes(&codes.front(), &codes.back() + 1); } catch (const std::range_error&) { res.error = "Invalid text encoding."sv; return res; @@ -507,6 +527,10 @@ ParseInfo MoonParser::parse(std::string_view codes, rule& r) { try { State state; res.node.set(pl::parse(*(res.codes), r, errors, &state)); + if (state.exportCount > 0) { + res.moduleName = std::move(state.moduleName); + res.exportDefault = state.exportDefault; + } } catch (const std::logic_error& err) { res.error = err.what(); return res; @@ -538,7 +562,7 @@ std::string MoonParser::toString(input::iterator begin, input::iterator end) { } input MoonParser::encode(std::string_view codes) { - return _converter.from_bytes(codes.begin(), codes.end()); + return _converter.from_bytes(&codes.front(), &codes.back() + 1); } std::string MoonParser::decode(const input& codes) { @@ -572,7 +596,6 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc count++; } } - auto line = Converter{}.to_bytes(std::wstring(begin, end)); int oldCol = loc->m_begin.m_col; int col = std::max(0, oldCol - 1); auto it = begin; @@ -582,6 +605,7 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc } ++it; } + auto line = Converter{}.to_bytes(std::wstring(begin, end)); Utils::replace(line, "\t"sv, " "sv); std::ostringstream buf; buf << loc->m_begin.m_line << ": "sv << msg << diff --git a/src/MoonP/moon_parser.h b/src/MoonP/moon_parser.h index 12f735b..eefcba5 100644 --- a/src/MoonP/moon_parser.h +++ b/src/MoonP/moon_parser.h @@ -26,6 +26,8 @@ struct ParseInfo { ast_ptr node; std::string error; std::unique_ptr codes; + bool exportDefault = false; + std::string moduleName; std::string errorMessage(std::string_view msg, const input_range* loc) const; }; @@ -72,10 +74,13 @@ protected: struct State { State() { indents.push(0); - stringOpen = -1; } + bool exportDefault = false; + int exportCount = 0; + int moduleFix = 0; + size_t stringOpen = 0; + std::string moduleName = "_module_0"; std::string buffer; - size_t stringOpen; std::stack indents; std::stack doStack; }; @@ -124,8 +129,8 @@ private: rule ImportNameList; rule import_literal_chain; rule WithExp; - rule PopDo; rule DisableDo; + rule PopDo; rule SwitchElse; rule SwitchBlock; rule IfElseIf; @@ -181,9 +186,9 @@ private: AST_RULE(SelfName) AST_RULE(KeyName) AST_RULE(VarArg) - AST_RULE(local_flag) AST_RULE(Seperator) AST_RULE(NameList) + AST_RULE(local_flag) AST_RULE(Local) AST_RULE(colon_import_name) AST_RULE(import_literal_inner) @@ -249,8 +254,10 @@ private: AST_RULE(class_member_list) AST_RULE(ClassBlock) AST_RULE(ClassDecl) - AST_RULE(export_values) - AST_RULE(export_op) + AST_RULE(global_values) + AST_RULE(global_op) + AST_RULE(Global) + AST_RULE(export_default) AST_RULE(Export) AST_RULE(variable_pair) AST_RULE(normal_pair) diff --git a/src/moonp.cpp b/src/moonp.cpp index ade1a1b..8026d50 100644 --- a/src/moonp.cpp +++ b/src/moonp.cpp @@ -81,10 +81,10 @@ int main(int narg, const char** args) { if (!targetPath.empty() && targetPath.back() != '/' && targetPath.back() != '\\') { targetPath.append("/"); } - std::list()>>> results; + std::list> results; for (const auto& file : files) { auto task = std::async(std::launch::async, [=]() { - std::ifstream input(file, input.in); + std::ifstream input(file, std::ios::in); if (input) { std::string s( (std::istreambuf_iterator(input)), @@ -135,7 +135,7 @@ int main(int narg, const char** args) { } else { targetFile = resultFile; } - std::ofstream output(targetFile, output.trunc | output.out); + std::ofstream output(targetFile, std::ios::trunc | std::ios::out); if (output) { const auto& codes = std::get<0>(result); output.write(codes.c_str(), codes.size()); -- cgit v1.2.3-55-g6feb