diff options
| author | Li Jin <dragon-fly@qq.com> | 2020-03-05 16:08:41 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2020-03-05 16:08:41 +0800 |
| commit | 890fc913737c62c5d7e51636e0535b7b318a0d89 (patch) | |
| tree | 8ca71fc3a2599ad1cbebcd3234dcb06292448037 /src/MoonP/moon_compiler.cpp | |
| parent | 3b94999e55df35d19616e87d7f3b6fddf5b8a30b (diff) | |
| download | yuescript-890fc913737c62c5d7e51636e0535b7b318a0d89.tar.gz yuescript-890fc913737c62c5d7e51636e0535b7b318a0d89.tar.bz2 yuescript-890fc913737c62c5d7e51636e0535b7b318a0d89.zip | |
move functions of old export statement to global statement, make export statement work with Lua module system.
Diffstat (limited to '')
| -rw-r--r-- | src/MoonP/moon_compiler.cpp | 192 |
1 files changed, 157 insertions, 35 deletions
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) { | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | const char* moonScriptVersion() { | 34 | const char* moonScriptVersion() { |
| 35 | return "0.5.0-r0.1.5"; | 35 | return "0.5.0-r0.2.0"; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | class MoonCompilerImpl { | 38 | class MoonCompilerImpl { |
| @@ -45,7 +45,10 @@ public: | |||
| 45 | try { | 45 | try { |
| 46 | str_list out; | 46 | str_list out; |
| 47 | pushScope(); | 47 | pushScope(); |
| 48 | transformBlock(_info.node.to<File_t>()->block, out, config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common); | 48 | enableReturn.push(_info.moduleName.empty()); |
| 49 | transformBlock(_info.node.to<File_t>()->block, out, | ||
| 50 | config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common, | ||
| 51 | nullptr, true); | ||
| 49 | popScope(); | 52 | popScope(); |
| 50 | if (config.lintGlobalVariable) { | 53 | if (config.lintGlobalVariable) { |
| 51 | globals = std::make_unique<std::list<GlobalVar>>(); | 54 | globals = std::make_unique<std::list<GlobalVar>>(); |
| @@ -86,6 +89,7 @@ private: | |||
| 86 | MoonParser _parser; | 89 | MoonParser _parser; |
| 87 | ParseInfo _info; | 90 | ParseInfo _info; |
| 88 | int _indentOffset = 0; | 91 | int _indentOffset = 0; |
| 92 | std::stack<bool> enableReturn; | ||
| 89 | std::list<std::unique_ptr<input>> _codeCache; | 93 | std::list<std::unique_ptr<input>> _codeCache; |
| 90 | std::stack<std::string> _withVars; | 94 | std::stack<std::string> _withVars; |
| 91 | std::stack<std::string> _continueVars; | 95 | std::stack<std::string> _continueVars; |
| @@ -98,16 +102,16 @@ private: | |||
| 98 | Capital = 1, | 102 | Capital = 1, |
| 99 | Any = 2 | 103 | Any = 2 |
| 100 | }; | 104 | }; |
| 101 | enum class ExportMode { | 105 | enum class GlobalMode { |
| 102 | None = 0, | 106 | None = 0, |
| 103 | Capital = 1, | 107 | Capital = 1, |
| 104 | Any = 2 | 108 | Any = 2 |
| 105 | }; | 109 | }; |
| 106 | struct Scope { | 110 | struct Scope { |
| 107 | ExportMode mode = ExportMode::None; | 111 | GlobalMode mode = GlobalMode::None; |
| 108 | std::unique_ptr<std::unordered_set<std::string>> vars; | 112 | std::unique_ptr<std::unordered_set<std::string>> vars; |
| 109 | std::unique_ptr<std::unordered_set<std::string>> allows; | 113 | std::unique_ptr<std::unordered_set<std::string>> allows; |
| 110 | std::unique_ptr<std::unordered_set<std::string>> exports; | 114 | std::unique_ptr<std::unordered_set<std::string>> globals; |
| 111 | }; | 115 | }; |
| 112 | std::list<Scope> _scopes; | 116 | std::list<Scope> _scopes; |
| 113 | static const std::string Empty; | 117 | static const std::string Empty; |
| @@ -153,11 +157,11 @@ private: | |||
| 153 | 157 | ||
| 154 | bool isDefined(const std::string& name) const { | 158 | bool isDefined(const std::string& name) const { |
| 155 | bool isDefined = false; | 159 | bool isDefined = false; |
| 156 | int mode = int(std::isupper(name[0]) ? ExportMode::Capital : ExportMode::Any); | 160 | int mode = int(std::isupper(name[0]) ? GlobalMode::Capital : GlobalMode::Any); |
| 157 | const auto& current = _scopes.back(); | 161 | const auto& current = _scopes.back(); |
| 158 | if (int(current.mode) >= mode) { | 162 | if (int(current.mode) >= mode) { |
| 159 | if (current.exports) { | 163 | if (current.globals) { |
| 160 | if (current.exports->find(name) != current.exports->end()) { | 164 | if (current.globals->find(name) != current.globals->end()) { |
| 161 | isDefined = true; | 165 | isDefined = true; |
| 162 | current.vars->insert(name); | 166 | current.vars->insert(name); |
| 163 | } | 167 | } |
| @@ -202,17 +206,17 @@ private: | |||
| 202 | scope.allows = std::make_unique<std::unordered_set<std::string>>(); | 206 | scope.allows = std::make_unique<std::unordered_set<std::string>>(); |
| 203 | } | 207 | } |
| 204 | 208 | ||
| 205 | void markVarExported(ExportMode mode, bool specified) { | 209 | void markVarGlobal(GlobalMode mode, bool specified) { |
| 206 | auto& scope = _scopes.back(); | 210 | auto& scope = _scopes.back(); |
| 207 | scope.mode = mode; | 211 | scope.mode = mode; |
| 208 | if (specified && !scope.exports) { | 212 | if (specified && !scope.globals) { |
| 209 | scope.exports = std::make_unique<std::unordered_set<std::string>>(); | 213 | scope.globals = std::make_unique<std::unordered_set<std::string>>(); |
| 210 | } | 214 | } |
| 211 | } | 215 | } |
| 212 | 216 | ||
| 213 | void addExportedVar(const std::string& name) { | 217 | void addGlobalVar(const std::string& name) { |
| 214 | auto& scope = _scopes.back(); | 218 | auto& scope = _scopes.back(); |
| 215 | scope.exports->insert(name); | 219 | scope.globals->insert(name); |
| 216 | } | 220 | } |
| 217 | 221 | ||
| 218 | void addToAllowList(const std::string& name) { | 222 | void addToAllowList(const std::string& name) { |
| @@ -457,6 +461,20 @@ private: | |||
| 457 | return Empty; | 461 | return Empty; |
| 458 | } | 462 | } |
| 459 | 463 | ||
| 464 | Variable_t* variableFrom(Exp_t* exp) { | ||
| 465 | BLOCK_START | ||
| 466 | auto value = singleValueFrom(exp); | ||
| 467 | BREAK_IF(!value); | ||
| 468 | auto chainValue = value->getByPath<ChainValue_t>(); | ||
| 469 | BREAK_IF(!chainValue); | ||
| 470 | BREAK_IF(chainValue->items.size() != 1); | ||
| 471 | auto callable = ast_cast<Callable_t>(chainValue->items.front()); | ||
| 472 | BREAK_IF(!callable); | ||
| 473 | return callable->item.as<Variable_t>(); | ||
| 474 | BLOCK_END | ||
| 475 | return nullptr; | ||
| 476 | } | ||
| 477 | |||
| 460 | bool isAssignable(const node_container& chainItems) const { | 478 | bool isAssignable(const node_container& chainItems) const { |
| 461 | if (chainItems.size() == 1) { | 479 | if (chainItems.size() == 1) { |
| 462 | auto firstItem = chainItems.back(); | 480 | auto firstItem = chainItems.back(); |
| @@ -647,6 +665,7 @@ private: | |||
| 647 | case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(content), out); break; | 665 | case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(content), out); break; |
| 648 | case id<Return_t>(): transformReturn(static_cast<Return_t*>(content), out); break; | 666 | case id<Return_t>(): transformReturn(static_cast<Return_t*>(content), out); break; |
| 649 | case id<Local_t>(): transformLocal(static_cast<Local_t*>(content), out); break; | 667 | case id<Local_t>(): transformLocal(static_cast<Local_t*>(content), out); break; |
| 668 | case id<Global_t>(): transformGlobal(static_cast<Global_t*>(content), out); break; | ||
| 650 | case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; | 669 | case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; |
| 651 | case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; | 670 | case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; |
| 652 | case id<ExpListAssign_t>(): { | 671 | case id<ExpListAssign_t>(): { |
| @@ -693,7 +712,7 @@ private: | |||
| 693 | break; | 712 | break; |
| 694 | } | 713 | } |
| 695 | } | 714 | } |
| 696 | throw std::logic_error(_info.errorMessage("Expression list must appear at the end of body or block."sv, expList)); | 715 | throw std::logic_error(_info.errorMessage("Expression list is not supported here."sv, expList)); |
| 697 | } | 716 | } |
| 698 | break; | 717 | break; |
| 699 | } | 718 | } |
| @@ -749,8 +768,8 @@ private: | |||
| 749 | return preDefs; | 768 | return preDefs; |
| 750 | } | 769 | } |
| 751 | 770 | ||
| 752 | str_list transformAssignDefs(ExpList_t* expList) { | 771 | str_list transformAssignDefs(ExpList_t* expList, bool markDefined = true) { |
| 753 | str_list preDefs; | 772 | str_list defs; |
| 754 | for (auto exp_ : expList->exprs.objects()) { | 773 | for (auto exp_ : expList->exprs.objects()) { |
| 755 | auto exp = static_cast<Exp_t*>(exp_); | 774 | auto exp = static_cast<Exp_t*>(exp_); |
| 756 | if (auto value = singleValueFrom(exp)) { | 775 | if (auto value = singleValueFrom(exp)) { |
| @@ -766,8 +785,8 @@ private: | |||
| 766 | if (self->name.is<self_t>()) name = "self"sv; | 785 | if (self->name.is<self_t>()) name = "self"sv; |
| 767 | } | 786 | } |
| 768 | BREAK_IF(name.empty()); | 787 | BREAK_IF(name.empty()); |
| 769 | if (addToScope(name)) { | 788 | if (!markDefined || addToScope(name)) { |
| 770 | preDefs.push_back(name); | 789 | defs.push_back(name); |
| 771 | } | 790 | } |
| 772 | BLOCK_END | 791 | BLOCK_END |
| 773 | } | 792 | } |
| @@ -775,7 +794,7 @@ private: | |||
| 775 | throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp)); | 794 | throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp)); |
| 776 | } | 795 | } |
| 777 | } | 796 | } |
| 778 | return preDefs; | 797 | return defs; |
| 779 | } | 798 | } |
| 780 | 799 | ||
| 781 | std::string getPredefine(const str_list& defs) { | 800 | std::string getPredefine(const str_list& defs) { |
| @@ -1650,6 +1669,7 @@ private: | |||
| 1650 | } | 1669 | } |
| 1651 | 1670 | ||
| 1652 | void transformFunLit(FunLit_t* funLit, str_list& out) { | 1671 | void transformFunLit(FunLit_t* funLit, str_list& out) { |
| 1672 | enableReturn.push(true); | ||
| 1653 | str_list temp; | 1673 | str_list temp; |
| 1654 | bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv; | 1674 | bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv; |
| 1655 | pushScope(); | 1675 | pushScope(); |
| @@ -1698,6 +1718,7 @@ private: | |||
| 1698 | } | 1718 | } |
| 1699 | } | 1719 | } |
| 1700 | out.push_back(clearBuf()); | 1720 | out.push_back(clearBuf()); |
| 1721 | enableReturn.pop(); | ||
| 1701 | } | 1722 | } |
| 1702 | 1723 | ||
| 1703 | void transformBody(Body_t* body, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 1724 | void transformBody(Body_t* body, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| @@ -1711,7 +1732,7 @@ private: | |||
| 1711 | } | 1732 | } |
| 1712 | } | 1733 | } |
| 1713 | 1734 | ||
| 1714 | void transformBlock(Block_t* block, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 1735 | void transformBlock(Block_t* block, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool isRoot = false) { |
| 1715 | const auto& nodes = block->statements.objects(); | 1736 | const auto& nodes = block->statements.objects(); |
| 1716 | LocalMode mode = LocalMode::None; | 1737 | LocalMode mode = LocalMode::None; |
| 1717 | Local_t* any = nullptr, *capital = nullptr; | 1738 | Local_t* any = nullptr, *capital = nullptr; |
| @@ -1768,7 +1789,7 @@ private: | |||
| 1768 | args->swap(a, arg); | 1789 | args->swap(a, arg); |
| 1769 | findPlaceHolder = true; | 1790 | findPlaceHolder = true; |
| 1770 | } else { | 1791 | } else { |
| 1771 | throw std::logic_error(_info.errorMessage("backcall placeholder can be used only in one place."sv, a)); | 1792 | throw std::logic_error(_info.errorMessage("Backcall placeholder can be used only in one place."sv, a)); |
| 1772 | } | 1793 | } |
| 1773 | } | 1794 | } |
| 1774 | } | 1795 | } |
| @@ -1792,9 +1813,10 @@ private: | |||
| 1792 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | 1813 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); |
| 1793 | expListAssign->expList.set(expList); | 1814 | expListAssign->expList.set(expList); |
| 1794 | newStmt->content.set(expListAssign); | 1815 | newStmt->content.set(expListAssign); |
| 1816 | newStmt->appendix.set(stmt->appendix); | ||
| 1795 | newBlock->statements.push_back(newStmt); | 1817 | newBlock->statements.push_back(newStmt); |
| 1796 | } | 1818 | } |
| 1797 | transformBlock(newBlock, out, usage, assignList); | 1819 | transformBlock(newBlock, out, usage, assignList, isRoot); |
| 1798 | return; | 1820 | return; |
| 1799 | } | 1821 | } |
| 1800 | if (auto local = stmt->content.as<Local_t>()) { | 1822 | if (auto local = stmt->content.as<Local_t>()) { |
| @@ -1838,6 +1860,15 @@ private: | |||
| 1838 | } | 1860 | } |
| 1839 | } | 1861 | } |
| 1840 | } | 1862 | } |
| 1863 | if (info.second) { | ||
| 1864 | auto defs = transformAssignDefs(info.second->expList, false); | ||
| 1865 | for (const auto& def : defs) { | ||
| 1866 | if (std::isupper(def[0]) && capital) { capital->decls.push_back(def); | ||
| 1867 | } else if (any) { | ||
| 1868 | any->decls.push_back(def); | ||
| 1869 | } | ||
| 1870 | } | ||
| 1871 | } | ||
| 1841 | BLOCK_START | 1872 | BLOCK_START |
| 1842 | auto assign = assignment->action.as<Assign_t>(); | 1873 | auto assign = assignment->action.as<Assign_t>(); |
| 1843 | BREAK_IF(!assign); | 1874 | BREAK_IF(!assign); |
| @@ -1865,10 +1896,14 @@ private: | |||
| 1865 | } | 1896 | } |
| 1866 | } | 1897 | } |
| 1867 | } | 1898 | } |
| 1899 | if (isRoot && !_info.moduleName.empty()) { | ||
| 1900 | block->statements.push_front(toAst<Statement_t>(_info.moduleName + s(_info.exportDefault ? "=nil"sv : "={}"sv), block)); | ||
| 1901 | } | ||
| 1868 | switch (usage) { | 1902 | switch (usage) { |
| 1869 | case ExpUsage::Closure: | 1903 | case ExpUsage::Closure: |
| 1870 | case ExpUsage::Return: { | 1904 | case ExpUsage::Return: { |
| 1871 | BLOCK_START | 1905 | BLOCK_START |
| 1906 | BREAK_IF(isRoot && !_info.moduleName.empty()); | ||
| 1872 | BREAK_IF(nodes.empty()); | 1907 | BREAK_IF(nodes.empty()); |
| 1873 | auto last = static_cast<Statement_t*>(nodes.back()); | 1908 | auto last = static_cast<Statement_t*>(nodes.back()); |
| 1874 | auto x = last; | 1909 | auto x = last; |
| @@ -1920,9 +1955,17 @@ private: | |||
| 1920 | } else { | 1955 | } else { |
| 1921 | out.push_back(Empty); | 1956 | out.push_back(Empty); |
| 1922 | } | 1957 | } |
| 1958 | if (isRoot && !_info.moduleName.empty()) { | ||
| 1959 | out.back().append(indent() + s("return "sv) + _info.moduleName + nlr(block)); | ||
| 1960 | } | ||
| 1923 | } | 1961 | } |
| 1924 | 1962 | ||
| 1925 | void transformReturn(Return_t* returnNode, str_list& out) { | 1963 | void transformReturn(Return_t* returnNode, str_list& out) { |
| 1964 | if (!enableReturn.top()) { | ||
| 1965 | ast_node* target = returnNode->valueList.get(); | ||
| 1966 | if (!target) target = returnNode; | ||
| 1967 | throw std::logic_error(_info.errorMessage("Illegal return statement here."sv, target)); | ||
| 1968 | } | ||
| 1926 | if (auto valueList = returnNode->valueList.get()) { | 1969 | if (auto valueList = returnNode->valueList.get()) { |
| 1927 | if (valueList->exprs.size() == 1) { | 1970 | if (valueList->exprs.size() == 1) { |
| 1928 | auto exp = static_cast<Exp_t*>(valueList->exprs.back()); | 1971 | auto exp = static_cast<Exp_t*>(valueList->exprs.back()); |
| @@ -3797,33 +3840,33 @@ private: | |||
| 3797 | out.push_back(_parser.toString(const_value)); | 3840 | out.push_back(_parser.toString(const_value)); |
| 3798 | } | 3841 | } |
| 3799 | 3842 | ||
| 3800 | void transformExport(Export_t* exportNode, str_list& out) { | 3843 | void transformGlobal(Global_t* global, str_list& out) { |
| 3801 | auto x = exportNode; | 3844 | auto x = global; |
| 3802 | auto item = exportNode->item.get(); | 3845 | auto item = global->item.get(); |
| 3803 | switch (item->getId()) { | 3846 | switch (item->getId()) { |
| 3804 | case id<ClassDecl_t>(): { | 3847 | case id<ClassDecl_t>(): { |
| 3805 | auto classDecl = static_cast<ClassDecl_t*>(item); | 3848 | auto classDecl = static_cast<ClassDecl_t*>(item); |
| 3806 | if (classDecl->name && classDecl->name->item->getId() == id<Variable_t>()) { | 3849 | if (classDecl->name && classDecl->name->item->getId() == id<Variable_t>()) { |
| 3807 | markVarExported(ExportMode::Any, true); | 3850 | markVarGlobal(GlobalMode::Any, true); |
| 3808 | addExportedVar(_parser.toString(classDecl->name->item)); | 3851 | addGlobalVar(_parser.toString(classDecl->name->item)); |
| 3809 | } | 3852 | } |
| 3810 | transformClassDecl(classDecl, out, ExpUsage::Common); | 3853 | transformClassDecl(classDecl, out, ExpUsage::Common); |
| 3811 | break; | 3854 | break; |
| 3812 | } | 3855 | } |
| 3813 | case id<export_op_t>(): | 3856 | case id<global_op_t>(): |
| 3814 | if (_parser.toString(item) == "*"sv) { | 3857 | if (_parser.toString(item) == "*"sv) { |
| 3815 | markVarExported(ExportMode::Any, false); | 3858 | markVarGlobal(GlobalMode::Any, false); |
| 3816 | } else { | 3859 | } else { |
| 3817 | markVarExported(ExportMode::Capital, false); | 3860 | markVarGlobal(GlobalMode::Capital, false); |
| 3818 | } | 3861 | } |
| 3819 | break; | 3862 | break; |
| 3820 | case id<export_values_t>(): { | 3863 | case id<global_values_t>(): { |
| 3821 | markVarExported(ExportMode::Any, true); | 3864 | markVarGlobal(GlobalMode::Any, true); |
| 3822 | auto values = exportNode->item.to<export_values_t>(); | 3865 | auto values = global->item.to<global_values_t>(); |
| 3823 | if (values->valueList) { | 3866 | if (values->valueList) { |
| 3824 | auto expList = x->new_ptr<ExpList_t>(); | 3867 | auto expList = x->new_ptr<ExpList_t>(); |
| 3825 | for (auto name : values->nameList->names.objects()) { | 3868 | for (auto name : values->nameList->names.objects()) { |
| 3826 | addExportedVar(_parser.toString(name)); | 3869 | addGlobalVar(_parser.toString(name)); |
| 3827 | auto callable = x->new_ptr<Callable_t>(); | 3870 | auto callable = x->new_ptr<Callable_t>(); |
| 3828 | callable->item.set(name); | 3871 | callable->item.set(name); |
| 3829 | auto chainValue = x->new_ptr<ChainValue_t>(); | 3872 | auto chainValue = x->new_ptr<ChainValue_t>(); |
| @@ -3842,7 +3885,7 @@ private: | |||
| 3842 | transformAssignment(assignment, out); | 3885 | transformAssignment(assignment, out); |
| 3843 | } else { | 3886 | } else { |
| 3844 | for (auto name : values->nameList->names.objects()) { | 3887 | for (auto name : values->nameList->names.objects()) { |
| 3845 | addExportedVar(_parser.toString(name)); | 3888 | addGlobalVar(_parser.toString(name)); |
| 3846 | } | 3889 | } |
| 3847 | } | 3890 | } |
| 3848 | break; | 3891 | break; |
| @@ -3851,6 +3894,85 @@ private: | |||
| 3851 | } | 3894 | } |
| 3852 | } | 3895 | } |
| 3853 | 3896 | ||
| 3897 | void transformExport(Export_t* exportNode, str_list& out) { | ||
| 3898 | auto x = exportNode; | ||
| 3899 | if (_scopes.size() > 1) { | ||
| 3900 | throw std::logic_error(_info.errorMessage("Can not do module export outside root block."sv, x)); | ||
| 3901 | } | ||
| 3902 | if (exportNode->assign) { | ||
| 3903 | auto expList = exportNode->target.to<ExpList_t>(); | ||
| 3904 | if (expList->exprs.size() != exportNode->assign->values.size()) { | ||
| 3905 | throw std::logic_error(_info.errorMessage("Left and right expressions must be matched in export statement."sv, x)); | ||
| 3906 | } | ||
| 3907 | for (auto _exp : expList->exprs.objects()) { | ||
| 3908 | auto exp = static_cast<Exp_t*>(_exp); | ||
| 3909 | if (!variableFrom(exp) && | ||
| 3910 | !exp->getByPath<Value_t, SimpleValue_t, TableLit_t>() && | ||
| 3911 | !exp->getByPath<Value_t, simple_table_t>()) { | ||
| 3912 | throw std::logic_error(_info.errorMessage("Left hand expressions must be variables in export statement."sv, x)); | ||
| 3913 | } | ||
| 3914 | } | ||
| 3915 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 3916 | assignment->expList.set(expList); | ||
| 3917 | assignment->action.set(exportNode->assign); | ||
| 3918 | transformAssignment(assignment, out); | ||
| 3919 | str_list names = transformAssignDefs(expList, false); | ||
| 3920 | auto info = extractDestructureInfo(assignment, true); | ||
| 3921 | if (!info.first.empty()) { | ||
| 3922 | for (const auto& destruct : info.first) | ||
| 3923 | for (const auto& item : destruct.items) | ||
| 3924 | if (item.isVariable) | ||
| 3925 | names.push_back(item.name); | ||
| 3926 | } | ||
| 3927 | if (_info.exportDefault) { | ||
| 3928 | out.back().append(indent() + _info.moduleName + s(" = "sv) + names.back() + nlr(exportNode)); | ||
| 3929 | } else { | ||
| 3930 | str_list lefts, rights; | ||
| 3931 | for (const auto& name : names) { | ||
| 3932 | lefts.push_back(_info.moduleName + s("[\""sv) + name + s("\"]"sv)); | ||
| 3933 | rights.push_back(name); | ||
| 3934 | } | ||
| 3935 | out.back().append(indent() + join(lefts,", "sv) + s(" = "sv) + join(rights, ", "sv) + nlr(exportNode)); | ||
| 3936 | } | ||
| 3937 | } else { | ||
| 3938 | if (_info.exportDefault) { | ||
| 3939 | auto exp = exportNode->target.to<Exp_t>(); | ||
| 3940 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 3941 | assignment->expList.set(toAst<ExpList_t>(_info.moduleName, x)); | ||
| 3942 | auto assign = x->new_ptr<Assign_t>(); | ||
| 3943 | assign->values.push_back(exp); | ||
| 3944 | assignment->action.set(assign); | ||
| 3945 | transformAssignment(assignment, out); | ||
| 3946 | } else { | ||
| 3947 | str_list temp; | ||
| 3948 | auto expList = exportNode->target.to<ExpList_t>(); | ||
| 3949 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 3950 | auto assignList = toAst<ExpList_t>(_info.moduleName + s("[#"sv) + _info.moduleName + s("+1]"sv), x); | ||
| 3951 | assignment->expList.set(assignList); | ||
| 3952 | for (auto exp : expList->exprs.objects()) { | ||
| 3953 | if (auto classDecl = exp->getByPath<Value_t, SimpleValue_t, ClassDecl_t>()) { | ||
| 3954 | if (classDecl->name && classDecl->name->item->getId() == id<Variable_t>()) { | ||
| 3955 | transformClassDecl(classDecl, temp, ExpUsage::Common); | ||
| 3956 | auto name = _parser.toString(classDecl->name->item); | ||
| 3957 | assignment->expList.set(toAst<ExpList_t>(_info.moduleName + s("[\""sv) + name + s("\"]"sv), x)); | ||
| 3958 | auto assign = x->new_ptr<Assign_t>(); | ||
| 3959 | assign->values.push_back(toAst<Exp_t>(name, x)); | ||
| 3960 | assignment->action.set(assign); | ||
| 3961 | transformAssignment(assignment, temp); | ||
| 3962 | assignment->expList.set(assignList); | ||
| 3963 | continue; | ||
| 3964 | } | ||
| 3965 | } | ||
| 3966 | auto assign = x->new_ptr<Assign_t>(); | ||
| 3967 | assign->values.push_back(exp); | ||
| 3968 | assignment->action.set(assign); | ||
| 3969 | transformAssignment(assignment, temp); | ||
| 3970 | } | ||
| 3971 | out.push_back(join(temp)); | ||
| 3972 | } | ||
| 3973 | } | ||
| 3974 | } | ||
| 3975 | |||
| 3854 | void transformTable(ast_node* table, const node_container& pairs, str_list& out) { | 3976 | void transformTable(ast_node* table, const node_container& pairs, str_list& out) { |
| 3855 | if (pairs.empty()) { | 3977 | if (pairs.empty()) { |
| 3856 | out.push_back(s("{ }"sv)); | 3978 | out.push_back(s("{ }"sv)); |
