aboutsummaryrefslogtreecommitdiff
path: root/src/MoonP/moon_compiler.cpp
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2020-03-05 16:08:41 +0800
committerLi Jin <dragon-fly@qq.com>2020-03-05 16:08:41 +0800
commit890fc913737c62c5d7e51636e0535b7b318a0d89 (patch)
tree8ca71fc3a2599ad1cbebcd3234dcb06292448037 /src/MoonP/moon_compiler.cpp
parent3b94999e55df35d19616e87d7f3b6fddf5b8a30b (diff)
downloadyuescript-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 'src/MoonP/moon_compiler.cpp')
-rw-r--r--src/MoonP/moon_compiler.cpp192
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
34const char* moonScriptVersion() { 34const char* moonScriptVersion() {
35 return "0.5.0-r0.1.5"; 35 return "0.5.0-r0.2.0";
36} 36}
37 37
38class MoonCompilerImpl { 38class 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));