diff options
Diffstat (limited to '')
-rw-r--r-- | src/MoonP/moon_compiler.cpp | 661 |
1 files changed, 605 insertions, 56 deletions
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index 1adfec9..046bf28 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp | |||
@@ -17,6 +17,14 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
17 | #include "MoonP/moon_parser.h" | 17 | #include "MoonP/moon_parser.h" |
18 | #include "MoonP/moon_compiler.h" | 18 | #include "MoonP/moon_compiler.h" |
19 | 19 | ||
20 | extern "C" { | ||
21 | |||
22 | #include "lua.h" | ||
23 | #include "lauxlib.h" | ||
24 | #include "lualib.h" | ||
25 | |||
26 | } // extern "C" | ||
27 | |||
20 | namespace MoonP { | 28 | namespace MoonP { |
21 | using namespace std::string_view_literals; | 29 | using namespace std::string_view_literals; |
22 | using namespace parserlib; | 30 | using namespace parserlib; |
@@ -32,11 +40,44 @@ inline std::string s(std::string_view sv) { | |||
32 | } | 40 | } |
33 | 41 | ||
34 | const char* moonScriptVersion() { | 42 | const char* moonScriptVersion() { |
35 | return "0.5.0-r0.2.0"; | 43 | return "0.5.0-r0.3.0"; |
36 | } | 44 | } |
37 | 45 | ||
46 | // name of table stored in lua registry | ||
47 | #define MOONP_MODULE "_modules_" | ||
48 | |||
38 | class MoonCompilerImpl { | 49 | class MoonCompilerImpl { |
39 | public: | 50 | public: |
51 | MoonCompilerImpl(lua_State* sharedState, | ||
52 | const std::function<void(void*)>& luaOpen, | ||
53 | bool sameModule, | ||
54 | std::string_view moduleName = {}): | ||
55 | L(sharedState), | ||
56 | _luaOpen(luaOpen), | ||
57 | _moduleName(moduleName) { | ||
58 | int top = -1; | ||
59 | BLOCK_START | ||
60 | BREAK_IF(!sameModule); | ||
61 | BREAK_IF(!L); | ||
62 | top = lua_gettop(L); | ||
63 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE | ||
64 | lua_rawget(L, LUA_REGISTRYINDEX); // reg[MOONP_MODULE], tb | ||
65 | BREAK_IF(lua_istable(L, -1) == 0); | ||
66 | int idx = static_cast<int>(lua_objlen(L, -1)); // idx = #tb, tb | ||
67 | BREAK_IF(idx == 0); | ||
68 | _useModule = true; | ||
69 | _sameModule = true; | ||
70 | BLOCK_END | ||
71 | if (top != -1) lua_settop(L, top); | ||
72 | } | ||
73 | |||
74 | ~MoonCompilerImpl() { | ||
75 | if (L && _stateOwner) { | ||
76 | lua_close(L); | ||
77 | L = nullptr; | ||
78 | } | ||
79 | } | ||
80 | |||
40 | std::tuple<std::string,std::string,GlobalVars> compile(std::string_view codes, const MoonConfig& config) { | 81 | std::tuple<std::string,std::string,GlobalVars> compile(std::string_view codes, const MoonConfig& config) { |
41 | _config = config; | 82 | _config = config; |
42 | _info = _parser.parse<File_t>(codes); | 83 | _info = _parser.parse<File_t>(codes); |
@@ -83,8 +124,23 @@ public: | |||
83 | _joinBuf.str(""); | 124 | _joinBuf.str(""); |
84 | _joinBuf.clear(); | 125 | _joinBuf.clear(); |
85 | _globals.clear(); | 126 | _globals.clear(); |
127 | if (_useModule) { | ||
128 | _useModule = false; | ||
129 | if (!_sameModule) { | ||
130 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE | ||
131 | lua_rawget(L, LUA_REGISTRYINDEX); // reg[MOONP_MODULE], tb | ||
132 | int idx = static_cast<int>(lua_objlen(L, -1)); | ||
133 | lua_pushnil(L); // tb nil | ||
134 | lua_rawseti(L, -2, idx); // tb[idx] = nil, tb | ||
135 | lua_pop(L, 1); // empty | ||
136 | } | ||
137 | } | ||
86 | } | 138 | } |
87 | private: | 139 | private: |
140 | bool _stateOwner = false; | ||
141 | bool _useModule = false; | ||
142 | bool _sameModule = false; | ||
143 | lua_State* L = nullptr; | ||
88 | MoonConfig _config; | 144 | MoonConfig _config; |
89 | MoonParser _parser; | 145 | MoonParser _parser; |
90 | ParseInfo _info; | 146 | ParseInfo _info; |
@@ -97,6 +153,9 @@ private: | |||
97 | std::ostringstream _buf; | 153 | std::ostringstream _buf; |
98 | std::ostringstream _joinBuf; | 154 | std::ostringstream _joinBuf; |
99 | const std::string _newLine = "\n"; | 155 | const std::string _newLine = "\n"; |
156 | std::function<void(void*)> _luaOpen; | ||
157 | std::string _moduleName; | ||
158 | |||
100 | enum class LocalMode { | 159 | enum class LocalMode { |
101 | None = 0, | 160 | None = 0, |
102 | Capital = 1, | 161 | Capital = 1, |
@@ -254,7 +313,7 @@ private: | |||
254 | 313 | ||
255 | const std::string nll(ast_node* node) const { | 314 | const std::string nll(ast_node* node) const { |
256 | if (_config.reserveLineNumber) { | 315 | if (_config.reserveLineNumber) { |
257 | return s(" -- "sv) + std::to_string(node->m_begin.m_line) + _newLine; | 316 | return s(" -- "sv) + std::to_string(node->m_begin.m_line + _config.lineOffset) + _newLine; |
258 | } else { | 317 | } else { |
259 | return _newLine; | 318 | return _newLine; |
260 | } | 319 | } |
@@ -262,7 +321,7 @@ private: | |||
262 | 321 | ||
263 | const std::string nlr(ast_node* node) const { | 322 | const std::string nlr(ast_node* node) const { |
264 | if (_config.reserveLineNumber) { | 323 | if (_config.reserveLineNumber) { |
265 | return s(" -- "sv) + std::to_string(node->m_end.m_line) + _newLine; | 324 | return s(" -- "sv) + std::to_string(node->m_end.m_line + _config.lineOffset) + _newLine; |
266 | } else { | 325 | } else { |
267 | return _newLine; | 326 | return _newLine; |
268 | } | 327 | } |
@@ -383,9 +442,13 @@ private: | |||
383 | template <class T> | 442 | template <class T> |
384 | ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { | 443 | ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { |
385 | auto res = _parser.parse<T>(s(codes)); | 444 | auto res = _parser.parse<T>(s(codes)); |
445 | int line = parent->m_begin.m_line; | ||
446 | int col = parent->m_begin.m_line; | ||
386 | res.node->traverse([&](ast_node* node) { | 447 | res.node->traverse([&](ast_node* node) { |
387 | node->m_begin.m_line = parent->m_begin.m_line; | 448 | node->m_begin.m_line = line; |
388 | node->m_end.m_line = parent->m_begin.m_line; | 449 | node->m_end.m_line = line; |
450 | node->m_begin.m_col = col; | ||
451 | node->m_end.m_col = col; | ||
389 | return traversal::Continue; | 452 | return traversal::Continue; |
390 | }); | 453 | }); |
391 | _codeCache.push_back(std::move(res.codes)); | 454 | _codeCache.push_back(std::move(res.codes)); |
@@ -401,10 +464,14 @@ private: | |||
401 | EndWithColon, | 464 | EndWithColon, |
402 | EndWithEOP, | 465 | EndWithEOP, |
403 | HasEOP, | 466 | HasEOP, |
404 | HasKeyword | 467 | HasKeyword, |
468 | Macro | ||
405 | }; | 469 | }; |
406 | 470 | ||
407 | ChainType specialChainValue(ChainValue_t* chainValue) const { | 471 | ChainType specialChainValue(ChainValue_t* chainValue) const { |
472 | if (isMacroChain(chainValue)) { | ||
473 | return ChainType::Macro; | ||
474 | } | ||
408 | if (ast_is<ColonChainItem_t>(chainValue->items.back())) { | 475 | if (ast_is<ColonChainItem_t>(chainValue->items.back())) { |
409 | return ChainType::EndWithColon; | 476 | return ChainType::EndWithColon; |
410 | } | 477 | } |
@@ -531,7 +598,7 @@ private: | |||
531 | for (auto exp_ : expList->exprs.objects()) { | 598 | for (auto exp_ : expList->exprs.objects()) { |
532 | Exp_t* exp = static_cast<Exp_t*>(exp_); | 599 | Exp_t* exp = static_cast<Exp_t*>(exp_); |
533 | if (!isAssignable(exp)) { | 600 | if (!isAssignable(exp)) { |
534 | throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp)); | 601 | throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, exp)); |
535 | } | 602 | } |
536 | } | 603 | } |
537 | } | 604 | } |
@@ -551,6 +618,21 @@ private: | |||
551 | return backcall; | 618 | return backcall; |
552 | } | 619 | } |
553 | 620 | ||
621 | bool isMacroChain(ChainValue_t* chainValue) const { | ||
622 | const auto& chainList = chainValue->items.objects(); | ||
623 | BLOCK_START | ||
624 | auto callable = ast_cast<Callable_t>(chainList.front()); | ||
625 | BREAK_IF(!callable); | ||
626 | BREAK_IF(!callable->item.is<MacroName_t>()); | ||
627 | if (chainList.size() == 1 || | ||
628 | !ast_is<Invoke_t,InvokeArgs_t>(*(++chainList.begin()))) { | ||
629 | throw std::logic_error(_info.errorMessage("macro expression must be followed by argument list"sv, callable)); | ||
630 | } | ||
631 | return true; | ||
632 | BLOCK_END | ||
633 | return false; | ||
634 | } | ||
635 | |||
554 | void transformStatement(Statement_t* statement, str_list& out) { | 636 | void transformStatement(Statement_t* statement, str_list& out) { |
555 | auto x = statement; | 637 | auto x = statement; |
556 | if (statement->appendix) { | 638 | if (statement->appendix) { |
@@ -667,6 +749,7 @@ private: | |||
667 | case id<Local_t>(): transformLocal(static_cast<Local_t*>(content), out); break; | 749 | 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; | 750 | case id<Global_t>(): transformGlobal(static_cast<Global_t*>(content), out); break; |
669 | case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; | 751 | case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; |
752 | case id<Macro_t>(): transformMacro(static_cast<Macro_t*>(content), out, false); break; | ||
670 | case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; | 753 | case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; |
671 | case id<ExpListAssign_t>(): { | 754 | case id<ExpListAssign_t>(): { |
672 | auto expListAssign = static_cast<ExpListAssign_t*>(content); | 755 | auto expListAssign = static_cast<ExpListAssign_t*>(content); |
@@ -712,7 +795,7 @@ private: | |||
712 | break; | 795 | break; |
713 | } | 796 | } |
714 | } | 797 | } |
715 | throw std::logic_error(_info.errorMessage("Expression list is not supported here."sv, expList)); | 798 | throw std::logic_error(_info.errorMessage("expression list is not supported here"sv, expList)); |
716 | } | 799 | } |
717 | break; | 800 | break; |
718 | } | 801 | } |
@@ -762,7 +845,7 @@ private: | |||
762 | BLOCK_END | 845 | BLOCK_END |
763 | } | 846 | } |
764 | } else { | 847 | } else { |
765 | throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp)); | 848 | throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, exp)); |
766 | } | 849 | } |
767 | } | 850 | } |
768 | return preDefs; | 851 | return preDefs; |
@@ -791,7 +874,7 @@ private: | |||
791 | BLOCK_END | 874 | BLOCK_END |
792 | } | 875 | } |
793 | } else { | 876 | } else { |
794 | throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp)); | 877 | throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, exp)); |
795 | } | 878 | } |
796 | } | 879 | } |
797 | return defs; | 880 | return defs; |
@@ -950,6 +1033,7 @@ private: | |||
950 | return; | 1033 | return; |
951 | } | 1034 | } |
952 | case ChainType::HasKeyword: | 1035 | case ChainType::HasKeyword: |
1036 | case ChainType::Macro: | ||
953 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList); | 1037 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList); |
954 | return; | 1038 | return; |
955 | case ChainType::Common: | 1039 | case ChainType::Common: |
@@ -1041,7 +1125,7 @@ private: | |||
1041 | const node_container* tableItems = nullptr; | 1125 | const node_container* tableItems = nullptr; |
1042 | if (ast_is<Exp_t>(node)) { | 1126 | if (ast_is<Exp_t>(node)) { |
1043 | auto item = singleValueFrom(node)->item.get(); | 1127 | auto item = singleValueFrom(node)->item.get(); |
1044 | if (!item) throw std::logic_error(_info.errorMessage("Invalid destructure value."sv, node)); | 1128 | if (!item) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); |
1045 | auto tbA = item->getByPath<TableLit_t>(); | 1129 | auto tbA = item->getByPath<TableLit_t>(); |
1046 | if (tbA) { | 1130 | if (tbA) { |
1047 | tableItems = &tbA->values.objects(); | 1131 | tableItems = &tbA->values.objects(); |
@@ -1059,7 +1143,7 @@ private: | |||
1059 | case id<Exp_t>(): { | 1143 | case id<Exp_t>(): { |
1060 | ++index; | 1144 | ++index; |
1061 | if (!isAssignable(static_cast<Exp_t*>(pair))) { | 1145 | if (!isAssignable(static_cast<Exp_t*>(pair))) { |
1062 | throw std::logic_error(_info.errorMessage("Can't destructure value."sv, pair)); | 1146 | throw std::logic_error(_info.errorMessage("can't destructure value"sv, pair)); |
1063 | } | 1147 | } |
1064 | auto value = singleValueFrom(pair); | 1148 | auto value = singleValueFrom(pair); |
1065 | auto item = value->item.get(); | 1149 | auto item = value->item.get(); |
@@ -1103,9 +1187,9 @@ private: | |||
1103 | case id<normal_pair_t>(): { | 1187 | case id<normal_pair_t>(): { |
1104 | auto np = static_cast<normal_pair_t*>(pair); | 1188 | auto np = static_cast<normal_pair_t*>(pair); |
1105 | auto key = np->key->getByPath<Name_t>(); | 1189 | auto key = np->key->getByPath<Name_t>(); |
1106 | if (!key) throw std::logic_error(_info.errorMessage("Invalid key for destructure."sv, np)); | 1190 | if (!key) throw std::logic_error(_info.errorMessage("invalid key for destructure"sv, np)); |
1107 | if (auto exp = np->value.as<Exp_t>()) { | 1191 | if (auto exp = np->value.as<Exp_t>()) { |
1108 | if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("Can't destructure value."sv, exp)); | 1192 | if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); |
1109 | auto item = singleValueFrom(exp)->item.get(); | 1193 | auto item = singleValueFrom(exp)->item.get(); |
1110 | if (ast_is<simple_table_t>(item) || | 1194 | if (ast_is<simple_table_t>(item) || |
1111 | item->getByPath<TableLit_t>()) { | 1195 | item->getByPath<TableLit_t>()) { |
@@ -1227,11 +1311,11 @@ private: | |||
1227 | auto action = assignment->action.get(); | 1311 | auto action = assignment->action.get(); |
1228 | switch (action->getId()) { | 1312 | switch (action->getId()) { |
1229 | case id<Update_t>(): { | 1313 | case id<Update_t>(): { |
1230 | if (expList->exprs.size() > 1) throw std::logic_error(_info.errorMessage("Can not apply update to multiple values."sv, expList)); | 1314 | if (expList->exprs.size() > 1) throw std::logic_error(_info.errorMessage("can not apply update to multiple values"sv, expList)); |
1231 | auto update = static_cast<Update_t*>(action); | 1315 | auto update = static_cast<Update_t*>(action); |
1232 | auto leftExp = static_cast<Exp_t*>(expList->exprs.objects().front()); | 1316 | auto leftExp = static_cast<Exp_t*>(expList->exprs.objects().front()); |
1233 | auto leftValue = singleValueFrom(leftExp); | 1317 | auto leftValue = singleValueFrom(leftExp); |
1234 | if (!leftValue) throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, leftExp)); | 1318 | if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp)); |
1235 | if (auto chain = leftValue->getByPath<ChainValue_t>()) { | 1319 | if (auto chain = leftValue->getByPath<ChainValue_t>()) { |
1236 | auto tmpChain = x->new_ptr<ChainValue_t>(); | 1320 | auto tmpChain = x->new_ptr<ChainValue_t>(); |
1237 | for (auto item : chain->items.objects()) { | 1321 | for (auto item : chain->items.objects()) { |
@@ -1544,7 +1628,7 @@ private: | |||
1544 | args->swap(a, arg); | 1628 | args->swap(a, arg); |
1545 | findPlaceHolder = true; | 1629 | findPlaceHolder = true; |
1546 | } else { | 1630 | } else { |
1547 | throw std::logic_error(_info.errorMessage("backcall placeholder can be used only in one place."sv, a)); | 1631 | throw std::logic_error(_info.errorMessage("backcall placeholder can be used only in one place"sv, a)); |
1548 | } | 1632 | } |
1549 | } | 1633 | } |
1550 | } | 1634 | } |
@@ -1576,7 +1660,7 @@ private: | |||
1576 | } | 1660 | } |
1577 | return; | 1661 | return; |
1578 | } else { | 1662 | } else { |
1579 | throw std::logic_error(_info.errorMessage("Backcall operator must be followed by chain value."sv, opValue->value)); | 1663 | throw std::logic_error(_info.errorMessage("backcall operator must be followed by chain value"sv, opValue->value)); |
1580 | } | 1664 | } |
1581 | } | 1665 | } |
1582 | } | 1666 | } |
@@ -1789,7 +1873,7 @@ private: | |||
1789 | args->swap(a, arg); | 1873 | args->swap(a, arg); |
1790 | findPlaceHolder = true; | 1874 | findPlaceHolder = true; |
1791 | } else { | 1875 | } else { |
1792 | throw std::logic_error(_info.errorMessage("Backcall placeholder can be used only in one place."sv, a)); | 1876 | throw std::logic_error(_info.errorMessage("backcall placeholder can be used only in one place"sv, a)); |
1793 | } | 1877 | } |
1794 | } | 1878 | } |
1795 | } | 1879 | } |
@@ -1820,21 +1904,27 @@ private: | |||
1820 | return; | 1904 | return; |
1821 | } | 1905 | } |
1822 | if (auto local = stmt->content.as<Local_t>()) { | 1906 | if (auto local = stmt->content.as<Local_t>()) { |
1823 | if (auto flag = local->name.as<local_flag_t>()) { | 1907 | switch (local->item->getId()) { |
1824 | LocalMode newMode = _parser.toString(flag) == "*"sv ? LocalMode::Any : LocalMode::Capital; | 1908 | case id<local_flag_t>(): { |
1825 | if (int(newMode) > int(mode)) { | 1909 | auto flag = local->item.to<local_flag_t>(); |
1826 | mode = newMode; | 1910 | LocalMode newMode = _parser.toString(flag) == "*"sv ? LocalMode::Any : LocalMode::Capital; |
1827 | } | 1911 | if (int(newMode) > int(mode)) { |
1828 | if (mode == LocalMode::Any) { | 1912 | mode = newMode; |
1829 | if (!any) any = local; | 1913 | } |
1830 | if (!capital) capital = local; | 1914 | if (mode == LocalMode::Any) { |
1831 | } else { | 1915 | if (!any) any = local; |
1832 | if (!capital) capital = local; | 1916 | if (!capital) capital = local; |
1917 | } else { | ||
1918 | if (!capital) capital = local; | ||
1919 | } | ||
1920 | break; | ||
1833 | } | 1921 | } |
1834 | } else { | 1922 | case id<local_values_t>(): { |
1835 | auto names = local->name.to<NameList_t>(); | 1923 | auto values = local->item.to<local_values_t>(); |
1836 | for (auto name : names->names.objects()) { | 1924 | for (auto name : values->nameList->names.objects()) { |
1837 | local->forceDecls.push_back(_parser.toString(name)); | 1925 | local->forceDecls.push_back(_parser.toString(name)); |
1926 | } | ||
1927 | break; | ||
1838 | } | 1928 | } |
1839 | } | 1929 | } |
1840 | } else if (mode != LocalMode::None) { | 1930 | } else if (mode != LocalMode::None) { |
@@ -1960,11 +2050,190 @@ private: | |||
1960 | } | 2050 | } |
1961 | } | 2051 | } |
1962 | 2052 | ||
2053 | void pushCurrentModule() { | ||
2054 | if (_useModule) { | ||
2055 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE | ||
2056 | lua_rawget(L, LUA_REGISTRYINDEX); // reg[MOONP_MODULE], tb | ||
2057 | int idx = static_cast<int>(lua_objlen(L, -1)); // idx = #tb, tb | ||
2058 | lua_rawgeti(L, -1, idx); // tb[idx], tb cur | ||
2059 | lua_remove(L, -2); // cur | ||
2060 | return; | ||
2061 | } | ||
2062 | _useModule = true; | ||
2063 | if (!L) { | ||
2064 | L = luaL_newstate(); | ||
2065 | if (_luaOpen) { | ||
2066 | _luaOpen(static_cast<void*>(L)); | ||
2067 | } | ||
2068 | _stateOwner = true; | ||
2069 | } | ||
2070 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE | ||
2071 | lua_rawget(L, LUA_REGISTRYINDEX); // reg[MOONP_MODULE], tb | ||
2072 | if (lua_isnil(L, -1) != 0) { // tb == nil | ||
2073 | lua_pop(L, 1); | ||
2074 | lua_newtable(L); // tb | ||
2075 | lua_pushliteral(L, MOONP_MODULE); // tb MOONP_MODULE | ||
2076 | lua_pushvalue(L, -2); // tb MOONP_MODULE tb | ||
2077 | lua_rawset(L, LUA_REGISTRYINDEX); // reg[MOONP_MODULE] = tb, tb | ||
2078 | } // tb | ||
2079 | int idx = static_cast<int>(lua_objlen(L, -1)); // idx = #tb, tb | ||
2080 | lua_newtable(L); // tb cur | ||
2081 | lua_pushvalue(L, -1); // tb cur cur | ||
2082 | lua_rawseti(L, -3, idx + 1); // tb[idx + 1] = cur, tb cur | ||
2083 | lua_remove(L, -2); // cur | ||
2084 | } | ||
2085 | |||
2086 | void pushMoonp(std::string_view name) { | ||
2087 | lua_getglobal(L, "package"); // package | ||
2088 | lua_getfield(L, -1, "loaded"); // package loaded | ||
2089 | lua_getfield(L, -1, "moonp"); // package loaded moonp | ||
2090 | lua_pushlstring(L, &name.front(), name.size()); // package loaded moonp name | ||
2091 | lua_gettable(L, -2); // loaded[name], package loaded moonp item | ||
2092 | lua_insert(L, -4); // item package loaded moonp | ||
2093 | lua_pop(L, 3); // item | ||
2094 | } | ||
2095 | |||
2096 | void hideStackTrace(bool hide) { | ||
2097 | lua_getglobal(L, "package"); // package | ||
2098 | lua_getfield(L, -1, "loaded"); // package loaded | ||
2099 | lua_getfield(L, -1, "moonp"); // package loaded moonp | ||
2100 | if (hide) { | ||
2101 | lua_pushboolean(L, 1); // package loaded moonp true | ||
2102 | } else { | ||
2103 | lua_pushnil(L); // package loaded moonp nil | ||
2104 | } | ||
2105 | lua_setfield(L, -2, "_hide_stacktrace_"); | ||
2106 | lua_pop(L, 3); // empty | ||
2107 | } | ||
2108 | |||
2109 | bool isModuleLoaded(std::string_view name) { | ||
2110 | int top = lua_gettop(L); | ||
2111 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE | ||
2112 | lua_rawget(L, LUA_REGISTRYINDEX); // modules | ||
2113 | lua_pushlstring(L, &name.front(), name.size()); | ||
2114 | lua_rawget(L, -2); // modules module | ||
2115 | if (lua_isnil(L, -1) != 0) { | ||
2116 | lua_settop(L, top); | ||
2117 | return false; | ||
2118 | } | ||
2119 | lua_settop(L, top); | ||
2120 | return true; | ||
2121 | } | ||
2122 | |||
2123 | void pushModuleTable(std::string_view name) { | ||
2124 | lua_pushliteral(L, MOONP_MODULE); // MOONP_MODULE | ||
2125 | lua_rawget(L, LUA_REGISTRYINDEX); // modules | ||
2126 | lua_pushlstring(L, &name.front(), name.size()); | ||
2127 | lua_rawget(L, -2); // modules module | ||
2128 | if (lua_isnil(L, -1) != 0) { | ||
2129 | lua_pop(L, 1); | ||
2130 | lua_newtable(L); // modules module | ||
2131 | lua_pushlstring(L, &name.front(), name.size()); | ||
2132 | lua_pushvalue(L, -2); // modules module name module | ||
2133 | lua_rawset(L, -4); // modules[name] = module, modules module | ||
2134 | } | ||
2135 | lua_remove(L, -2); // module | ||
2136 | } | ||
2137 | |||
2138 | void pushOptions(int lineOffset) { | ||
2139 | lua_newtable(L); | ||
2140 | lua_pushliteral(L, "lint_global"); | ||
2141 | lua_pushboolean(L, 0); | ||
2142 | lua_rawset(L, -3); | ||
2143 | lua_pushliteral(L, "implicit_return_root"); | ||
2144 | lua_pushboolean(L, 1); | ||
2145 | lua_rawset(L, -3); | ||
2146 | lua_pushliteral(L, "reserve_line_number"); | ||
2147 | lua_pushboolean(L, 1); | ||
2148 | lua_rawset(L, -3); | ||
2149 | lua_pushliteral(L, "same_module"); | ||
2150 | lua_pushboolean(L, 1); | ||
2151 | lua_rawset(L, -3); | ||
2152 | lua_pushliteral(L, "line_offset"); | ||
2153 | lua_pushinteger(L, lineOffset); | ||
2154 | lua_rawset(L, -3); | ||
2155 | } | ||
2156 | |||
2157 | void transformMacro(Macro_t* macro, str_list& out, bool exporting) { | ||
2158 | auto type = _parser.toString(macro->type); | ||
2159 | auto macroName = _parser.toString(macro->name); | ||
2160 | auto argsDef = macro->macroLit->argsDef.get(); | ||
2161 | str_list newArgs; | ||
2162 | if (argsDef) { | ||
2163 | for (auto def_ : argsDef->definitions.objects()) { | ||
2164 | auto def = static_cast<FnArgDef_t*>(def_); | ||
2165 | if (def->name.is<SelfName_t>()) { | ||
2166 | throw std::logic_error(_info.errorMessage("self name is not supported here"sv, def->name)); | ||
2167 | } else { | ||
2168 | std::string defVal; | ||
2169 | if (def->defaultValue) { | ||
2170 | defVal = _parser.toString(def->defaultValue); | ||
2171 | Utils::trim(defVal); | ||
2172 | defVal.insert(0, "=[==========["sv); | ||
2173 | defVal.append("]==========]"sv); | ||
2174 | } | ||
2175 | newArgs.emplace_back(_parser.toString(def->name) + defVal); | ||
2176 | } | ||
2177 | } | ||
2178 | if (argsDef->varArg) { | ||
2179 | newArgs.emplace_back(_parser.toString(argsDef->varArg)); | ||
2180 | } | ||
2181 | } | ||
2182 | _buf << "fmacro = ("sv << join(newArgs, ","sv) << ")->"sv; | ||
2183 | _buf << _parser.toString(macro->macroLit->body) << '\n'; | ||
2184 | _buf << "{fmacro, \"" << type << "\"}"sv; | ||
2185 | auto macroCodes = clearBuf(); | ||
2186 | _buf << "=(macro "sv << macroName << ")"; | ||
2187 | auto chunkName = clearBuf(); | ||
2188 | pushCurrentModule(); // cur | ||
2189 | int top = lua_gettop(L) - 1; | ||
2190 | pushMoonp("loadstring"sv); // cur loadstring | ||
2191 | lua_pushlstring(L, macroCodes.c_str(), macroCodes.size()); // cur loadstring codes | ||
2192 | lua_pushlstring(L, chunkName.c_str(), chunkName.size()); // cur loadstring codes chunk | ||
2193 | pushOptions(macro->m_begin.m_line - 1); // cur loadstring codes chunk options | ||
2194 | if (lua_pcall(L, 3, 2, 0) != 0) { // loadstring(codes,chunk,options), cur f err | ||
2195 | std::string err = lua_tostring(L, -1); | ||
2196 | lua_settop(L, top); | ||
2197 | throw std::logic_error(_info.errorMessage(s("fail to load macro codes\n"sv) + err, macro->macroLit)); | ||
2198 | } // cur f err | ||
2199 | if (lua_isnil(L, -2) != 0) { // f == nil, cur f err | ||
2200 | std::string err = lua_tostring(L, -1); | ||
2201 | lua_settop(L, top); | ||
2202 | throw std::logic_error(_info.errorMessage(s("fail to load macro codes, at (macro "sv) + macroName + s("): "sv) + err, macro->macroLit)); | ||
2203 | } | ||
2204 | lua_pop(L, 1); // cur f | ||
2205 | pushMoonp("pcall"sv); // cur f pcall | ||
2206 | lua_insert(L, -2); // cur pcall f | ||
2207 | if (lua_pcall(L, 1, 2, 0) != 0) { // f(), cur success macro | ||
2208 | std::string err = lua_tostring(L, -1); | ||
2209 | lua_settop(L, top); | ||
2210 | throw std::logic_error(_info.errorMessage(s("fail to generate macro function\n"sv) + err, macro->macroLit)); | ||
2211 | } // cur success res | ||
2212 | if (lua_toboolean(L, -2) == 0) { | ||
2213 | std::string err = lua_tostring(L, -1); | ||
2214 | lua_settop(L, top); | ||
2215 | throw std::logic_error(_info.errorMessage(s("fail to generate macro function\n"sv) + err, macro->macroLit)); | ||
2216 | } // cur true macro | ||
2217 | lua_remove(L, -2); // cur macro | ||
2218 | if (exporting && !_moduleName.empty()) { | ||
2219 | pushModuleTable(_moduleName); // cur macro module | ||
2220 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name | ||
2221 | lua_pushvalue(L, -3); // cur macro module name macro | ||
2222 | lua_rawset(L, -3); // cur macro module | ||
2223 | lua_pop(L, 1); | ||
2224 | } // cur macro | ||
2225 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro name | ||
2226 | lua_insert(L, -2); // cur name macro | ||
2227 | lua_rawset(L, -3); // cur[name] = macro, cur | ||
2228 | lua_settop(L, top); | ||
2229 | out.push_back(Empty); | ||
2230 | } | ||
2231 | |||
1963 | void transformReturn(Return_t* returnNode, str_list& out) { | 2232 | void transformReturn(Return_t* returnNode, str_list& out) { |
1964 | if (!enableReturn.top()) { | 2233 | if (!enableReturn.top()) { |
1965 | ast_node* target = returnNode->valueList.get(); | 2234 | ast_node* target = returnNode->valueList.get(); |
1966 | if (!target) target = returnNode; | 2235 | if (!target) target = returnNode; |
1967 | throw std::logic_error(_info.errorMessage("Illegal return statement here."sv, target)); | 2236 | throw std::logic_error(_info.errorMessage("illegal return statement here"sv, target)); |
1968 | } | 2237 | } |
1969 | if (auto valueList = returnNode->valueList.get()) { | 2238 | if (auto valueList = returnNode->valueList.get()) { |
1970 | if (valueList->exprs.size() == 1) { | 2239 | if (valueList->exprs.size() == 1) { |
@@ -2286,7 +2555,7 @@ private: | |||
2286 | chainValue->items.pop_back(); | 2555 | chainValue->items.pop_back(); |
2287 | if (chainValue->items.empty()) { | 2556 | if (chainValue->items.empty()) { |
2288 | if (_withVars.empty()) { | 2557 | if (_withVars.empty()) { |
2289 | throw std::logic_error(_info.errorMessage("Short dot/colon syntax must be called within a with block."sv, x)); | 2558 | throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); |
2290 | } | 2559 | } |
2291 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), x)); | 2560 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), x)); |
2292 | } | 2561 | } |
@@ -2417,7 +2686,7 @@ private: | |||
2417 | case id<DotChainItem_t>(): | 2686 | case id<DotChainItem_t>(): |
2418 | case id<ColonChainItem_t>(): | 2687 | case id<ColonChainItem_t>(): |
2419 | if (_withVars.empty()) { | 2688 | if (_withVars.empty()) { |
2420 | throw std::logic_error(_info.errorMessage("Short dot/colon syntax must be called within a with block."sv, chainList.front())); | 2689 | throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, chainList.front())); |
2421 | } else { | 2690 | } else { |
2422 | baseChain->items.push_back(toAst<Callable_t>(_withVars.top(), x)); | 2691 | baseChain->items.push_back(toAst<Callable_t>(_withVars.top(), x)); |
2423 | } | 2692 | } |
@@ -2499,7 +2768,7 @@ private: | |||
2499 | case id<DotChainItem_t>(): | 2768 | case id<DotChainItem_t>(): |
2500 | case id<ColonChainItem_t>(): | 2769 | case id<ColonChainItem_t>(): |
2501 | if (_withVars.empty()) { | 2770 | if (_withVars.empty()) { |
2502 | throw std::logic_error(_info.errorMessage("Short dot/colon syntax must be called within a with block."sv, x)); | 2771 | throw std::logic_error(_info.errorMessage("short dot/colon syntax must be called within a with block"sv, x)); |
2503 | } else { | 2772 | } else { |
2504 | temp.push_back(_withVars.top()); | 2773 | temp.push_back(_withVars.top()); |
2505 | } | 2774 | } |
@@ -2531,7 +2800,7 @@ private: | |||
2531 | --next; | 2800 | --next; |
2532 | } | 2801 | } |
2533 | if (!ast_is<Invoke_t, InvokeArgs_t>(followItem)) { | 2802 | if (!ast_is<Invoke_t, InvokeArgs_t>(followItem)) { |
2534 | throw std::logic_error(_info.errorMessage("Colon chain item must be followed by invoke arguments."sv, colonItem)); | 2803 | throw std::logic_error(_info.errorMessage("colon chain item must be followed by invoke arguments"sv, colonItem)); |
2535 | } | 2804 | } |
2536 | if (colonItem->name.is<LuaKeyword_t>()) { | 2805 | if (colonItem->name.is<LuaKeyword_t>()) { |
2537 | std::string callVar; | 2806 | std::string callVar; |
@@ -2667,7 +2936,172 @@ private: | |||
2667 | } | 2936 | } |
2668 | } | 2937 | } |
2669 | 2938 | ||
2939 | std::pair<std::string,std::string> expandMacroStr(ChainValue_t* chainValue) { | ||
2940 | const auto& chainList = chainValue->items.objects(); | ||
2941 | auto callable = ast_cast<Callable_t>(chainList.front()); | ||
2942 | auto macroName = _parser.toString(callable->item.to<MacroName_t>()->name); | ||
2943 | if (!_useModule) { | ||
2944 | throw std::logic_error(_info.errorMessage("can not resolve macro", callable->item)); | ||
2945 | } | ||
2946 | pushCurrentModule(); // cur | ||
2947 | int top = lua_gettop(L) - 1; | ||
2948 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macroName | ||
2949 | lua_rawget(L, -2); // cur[macroName], cur macro | ||
2950 | if (lua_istable(L, -1) == 0) { | ||
2951 | lua_settop(L, top); | ||
2952 | throw std::logic_error(_info.errorMessage("can not resolve macro", callable->item)); | ||
2953 | } | ||
2954 | lua_rawgeti(L, -1, 1); // cur macro func | ||
2955 | pushMoonp("pcall"sv); // cur macro func pcall | ||
2956 | lua_insert(L, -2); // cur macro pcall func | ||
2957 | auto item = *(++chainList.begin()); | ||
2958 | const node_container* args = nullptr; | ||
2959 | if (auto invoke = ast_cast<Invoke_t>(item)) { | ||
2960 | args = &invoke->args.objects(); | ||
2961 | } else { | ||
2962 | args = &ast_to<InvokeArgs_t>(item)->args.objects(); | ||
2963 | } | ||
2964 | for (auto arg : *args) { | ||
2965 | std::string str; | ||
2966 | if (auto exp = ast_cast<Exp_t>(arg)) { | ||
2967 | // patch for backcall operator support | ||
2968 | BLOCK_START | ||
2969 | BREAK_IF(arg->m_begin.m_line != arg->m_end.m_line || | ||
2970 | arg->m_begin.m_col != arg->m_end.m_col); | ||
2971 | BREAK_IF(!exp->opValues.empty()); | ||
2972 | auto chainValue = exp->getByPath<Value_t, ChainValue_t>(); | ||
2973 | BREAK_IF(!chainValue); | ||
2974 | BREAK_IF(!isMacroChain(chainValue)); | ||
2975 | BREAK_IF(chainValue->items.size() != 2); | ||
2976 | std::string type, codes; | ||
2977 | std::tie(type, codes) = expandMacroStr(chainValue); | ||
2978 | str = codes; | ||
2979 | BLOCK_END | ||
2980 | if (str.empty()) { | ||
2981 | str = _parser.toString(exp->value); | ||
2982 | for (auto opVal : exp->opValues.objects()) { | ||
2983 | str += _parser.toString(opVal); | ||
2984 | } | ||
2985 | } | ||
2986 | } else str = _parser.toString(arg); | ||
2987 | Utils::trim(str); | ||
2988 | lua_pushlstring(L, str.c_str(), str.size()); | ||
2989 | } // cur macro pcall func args... | ||
2990 | hideStackTrace(true); | ||
2991 | bool success = lua_pcall(L, static_cast<int>(args->size()) + 1, 2, 0) == 0; | ||
2992 | if (!success) { // cur macro err | ||
2993 | std::string err = lua_tostring(L, -1); | ||
2994 | lua_settop(L, top); | ||
2995 | throw std::logic_error(_info.errorMessage(s("fail to expand macro\n"sv) + err, callable)); | ||
2996 | } // cur macro success res | ||
2997 | hideStackTrace(false); | ||
2998 | if (lua_toboolean(L, -2) == 0) { | ||
2999 | std::string err = lua_tostring(L, -1); | ||
3000 | lua_settop(L, top); | ||
3001 | throw std::logic_error(_info.errorMessage(s("fail to expand macro\n"sv) + err, callable)); | ||
3002 | } | ||
3003 | lua_remove(L, -2); // cur macro res | ||
3004 | if (lua_isstring(L, -1) == 0) { | ||
3005 | lua_settop(L, top); | ||
3006 | throw std::logic_error(_info.errorMessage(s("macro function must return string with expanded codes"sv), callable)); | ||
3007 | } // cur macro codes | ||
3008 | lua_rawgeti(L, -2, 2); // cur macro codes type | ||
3009 | std::string type = lua_tostring(L, -1); | ||
3010 | std::string codes = lua_tostring(L, -2); | ||
3011 | lua_settop(L, top); | ||
3012 | return {type, codes}; | ||
3013 | } | ||
3014 | |||
3015 | std::pair<ast_ptr<false,ast_node>, std::unique_ptr<input>> expandMacro(ChainValue_t* chainValue, ExpUsage usage) { | ||
3016 | auto x = chainValue; | ||
3017 | const auto& chainList = chainValue->items.objects(); | ||
3018 | std::string type, codes; | ||
3019 | std::tie(type, codes) = expandMacroStr(chainValue); | ||
3020 | std::string targetType(usage == ExpUsage::Common ? "block"sv : "expr"sv); | ||
3021 | if (type != targetType) { | ||
3022 | throw std::logic_error(_info.errorMessage(s("macro type mismatch, "sv) + targetType + s(" expected, got "sv) + type + '.', x)); | ||
3023 | } | ||
3024 | ParseInfo info; | ||
3025 | if (usage == ExpUsage::Common) { | ||
3026 | if (codes.empty()) { | ||
3027 | return {x->new_ptr<Block_t>().get(),std::move(info.codes)}; | ||
3028 | } | ||
3029 | info = _parser.parse<Block_t>(codes); | ||
3030 | } else { | ||
3031 | info = _parser.parse<Exp_t>(codes); | ||
3032 | } | ||
3033 | if (!info.node) { | ||
3034 | throw std::logic_error(_info.errorMessage("fail to expand macro: " + info.error, x)); | ||
3035 | } | ||
3036 | int line = x->m_begin.m_line; | ||
3037 | int col = x->m_begin.m_col; | ||
3038 | info.node->traverse([&](ast_node* node) { | ||
3039 | node->m_begin.m_line = line; | ||
3040 | node->m_end.m_line = line; | ||
3041 | node->m_begin.m_col = col; | ||
3042 | node->m_end.m_col = col; | ||
3043 | return traversal::Continue; | ||
3044 | }); | ||
3045 | if (usage == ExpUsage::Common) { | ||
3046 | return {info.node,std::move(info.codes)}; | ||
3047 | } else { | ||
3048 | ast_ptr<false, Exp_t> exp; | ||
3049 | exp.set(info.node); | ||
3050 | if (!exp->opValues.empty() || chainList.size() > 2) { | ||
3051 | auto paren = x->new_ptr<Parens_t>(); | ||
3052 | paren->expr.set(exp); | ||
3053 | auto callable = x->new_ptr<Callable_t>(); | ||
3054 | callable->item.set(paren); | ||
3055 | auto newChain = x->new_ptr<ChainValue_t>(); | ||
3056 | newChain->items.push_back(callable); | ||
3057 | auto it = chainList.begin(); | ||
3058 | it++; it++; | ||
3059 | for (; it != chainList.end(); ++it) { | ||
3060 | newChain->items.push_back(*it); | ||
3061 | } | ||
3062 | auto value = x->new_ptr<Value_t>(); | ||
3063 | value->item.set(newChain); | ||
3064 | exp = x->new_ptr<Exp_t>(); | ||
3065 | exp->value.set(value); | ||
3066 | } | ||
3067 | return {exp.get(),std::move(info.codes)}; | ||
3068 | } | ||
3069 | } | ||
3070 | |||
2670 | void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 3071 | void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
3072 | if (isMacroChain(chainValue)) { | ||
3073 | ast_ptr<false,ast_node> node; | ||
3074 | std::unique_ptr<input> codes; | ||
3075 | std::tie(node,codes) = expandMacro(chainValue, usage); | ||
3076 | if (usage == ExpUsage::Common) { | ||
3077 | transformBlock(node.to<Block_t>(), out, usage, assignList); | ||
3078 | } else { | ||
3079 | auto x = chainValue; | ||
3080 | switch (usage) { | ||
3081 | case ExpUsage::Assignment: { | ||
3082 | auto assign = x->new_ptr<Assign_t>(); | ||
3083 | assign->values.push_back(node); | ||
3084 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
3085 | assignment->expList.set(assignList); | ||
3086 | assignment->action.set(assign); | ||
3087 | transformAssignment(assignment, out); | ||
3088 | break; | ||
3089 | } | ||
3090 | case ExpUsage::Return: { | ||
3091 | auto expListLow = x->new_ptr<ExpListLow_t>(); | ||
3092 | expListLow->exprs.push_back(node); | ||
3093 | auto returnNode = x->new_ptr<Return_t>(); | ||
3094 | returnNode->valueList.set(expListLow); | ||
3095 | transformReturn(returnNode, out); | ||
3096 | break; | ||
3097 | } | ||
3098 | default: | ||
3099 | transformExp(node.to<Exp_t>(), out, usage); | ||
3100 | break; | ||
3101 | } | ||
3102 | } | ||
3103 | return; | ||
3104 | } | ||
2671 | const auto& chainList = chainValue->items.objects(); | 3105 | const auto& chainList = chainValue->items.objects(); |
2672 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { | 3106 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { |
2673 | return; | 3107 | return; |
@@ -2700,7 +3134,7 @@ private: | |||
2700 | } | 3134 | } |
2701 | 3135 | ||
2702 | void transformSlice(Slice_t* slice, str_list&) { | 3136 | void transformSlice(Slice_t* slice, str_list&) { |
2703 | throw std::logic_error(_info.errorMessage("Slice syntax not supported here."sv, slice)); | 3137 | throw std::logic_error(_info.errorMessage("slice syntax not supported here"sv, slice)); |
2704 | } | 3138 | } |
2705 | 3139 | ||
2706 | void transformInvoke(Invoke_t* invoke, str_list& out) { | 3140 | void transformInvoke(Invoke_t* invoke, str_list& out) { |
@@ -2895,7 +3329,7 @@ private: | |||
2895 | auto indexVar = getUnusedName("_index_"sv); | 3329 | auto indexVar = getUnusedName("_index_"sv); |
2896 | varAfter.push_back(indexVar); | 3330 | varAfter.push_back(indexVar); |
2897 | auto value = singleValueFrom(star_exp->value); | 3331 | auto value = singleValueFrom(star_exp->value); |
2898 | if (!value) throw std::logic_error(_info.errorMessage("Invalid star syntax."sv, star_exp)); | 3332 | if (!value) throw std::logic_error(_info.errorMessage("invalid star syntax"sv, star_exp)); |
2899 | bool endWithSlice = false; | 3333 | bool endWithSlice = false; |
2900 | BLOCK_START | 3334 | BLOCK_START |
2901 | auto chainValue = value->item.as<ChainValue_t>(); | 3335 | auto chainValue = value->item.as<ChainValue_t>(); |
@@ -3345,7 +3779,7 @@ private: | |||
3345 | std::string assignItem; | 3779 | std::string assignItem; |
3346 | if (assignable) { | 3780 | if (assignable) { |
3347 | if (!isAssignable(assignable)) { | 3781 | if (!isAssignable(assignable)) { |
3348 | throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, assignable)); | 3782 | throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, assignable)); |
3349 | } | 3783 | } |
3350 | bool newDefined = false; | 3784 | bool newDefined = false; |
3351 | std::tie(className, newDefined) = defineClassVariable(assignable); | 3785 | std::tie(className, newDefined) = defineClassVariable(assignable); |
@@ -3586,7 +4020,7 @@ private: | |||
3586 | if (selfName) { | 4020 | if (selfName) { |
3587 | type = MemType::Property; | 4021 | type = MemType::Property; |
3588 | auto name = ast_cast<self_name_t>(selfName->name); | 4022 | auto name = ast_cast<self_name_t>(selfName->name); |
3589 | if (!name) throw std::logic_error(_info.errorMessage("Invalid class poperty name."sv, selfName->name)); | 4023 | if (!name) throw std::logic_error(_info.errorMessage("invalid class poperty name"sv, selfName->name)); |
3590 | newSuperCall = classVar + s(".__parent."sv) + _parser.toString(name->name); | 4024 | newSuperCall = classVar + s(".__parent."sv) + _parser.toString(name->name); |
3591 | } else { | 4025 | } else { |
3592 | auto x = keyName; | 4026 | auto x = keyName; |
@@ -3897,19 +4331,19 @@ private: | |||
3897 | void transformExport(Export_t* exportNode, str_list& out) { | 4331 | void transformExport(Export_t* exportNode, str_list& out) { |
3898 | auto x = exportNode; | 4332 | auto x = exportNode; |
3899 | if (_scopes.size() > 1) { | 4333 | if (_scopes.size() > 1) { |
3900 | throw std::logic_error(_info.errorMessage("Can not do module export outside root block."sv, x)); | 4334 | throw std::logic_error(_info.errorMessage("can not do module export outside root block"sv, x)); |
3901 | } | 4335 | } |
3902 | if (exportNode->assign) { | 4336 | if (exportNode->assign) { |
3903 | auto expList = exportNode->target.to<ExpList_t>(); | 4337 | auto expList = exportNode->target.to<ExpList_t>(); |
3904 | if (expList->exprs.size() != exportNode->assign->values.size()) { | 4338 | 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)); | 4339 | throw std::logic_error(_info.errorMessage("left and right expressions must be matched in export statement"sv, x)); |
3906 | } | 4340 | } |
3907 | for (auto _exp : expList->exprs.objects()) { | 4341 | for (auto _exp : expList->exprs.objects()) { |
3908 | auto exp = static_cast<Exp_t*>(_exp); | 4342 | auto exp = static_cast<Exp_t*>(_exp); |
3909 | if (!variableFrom(exp) && | 4343 | if (!variableFrom(exp) && |
3910 | !exp->getByPath<Value_t, SimpleValue_t, TableLit_t>() && | 4344 | !exp->getByPath<Value_t, SimpleValue_t, TableLit_t>() && |
3911 | !exp->getByPath<Value_t, simple_table_t>()) { | 4345 | !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)); | 4346 | throw std::logic_error(_info.errorMessage("left hand expressions must be variables in export statement"sv, x)); |
3913 | } | 4347 | } |
3914 | } | 4348 | } |
3915 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 4349 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
@@ -3935,7 +4369,9 @@ private: | |||
3935 | out.back().append(indent() + join(lefts,", "sv) + s(" = "sv) + join(rights, ", "sv) + nlr(exportNode)); | 4369 | out.back().append(indent() + join(lefts,", "sv) + s(" = "sv) + join(rights, ", "sv) + nlr(exportNode)); |
3936 | } | 4370 | } |
3937 | } else { | 4371 | } else { |
3938 | if (_info.exportDefault) { | 4372 | if (auto macro = exportNode->target.as<Macro_t>()) { |
4373 | transformMacro(macro, out, true); | ||
4374 | } else if (_info.exportDefault) { | ||
3939 | auto exp = exportNode->target.to<Exp_t>(); | 4375 | auto exp = exportNode->target.to<Exp_t>(); |
3940 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 4376 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
3941 | assignment->expList.set(toAst<ExpList_t>(_info.moduleName, x)); | 4377 | assignment->expList.set(toAst<ExpList_t>(_info.moduleName, x)); |
@@ -4218,14 +4654,102 @@ private: | |||
4218 | out.push_back(join(temp)); | 4654 | out.push_back(join(temp)); |
4219 | } | 4655 | } |
4220 | 4656 | ||
4657 | std::string moduleNameFrom(ImportLiteral_t* literal) { | ||
4658 | auto name = _parser.toString(literal->inners.back()); | ||
4659 | Utils::replace(name, "-"sv, "_"sv); | ||
4660 | Utils::replace(name, " "sv, "_"sv); | ||
4661 | return name; | ||
4662 | } | ||
4663 | |||
4221 | void transformImportAs(ImportAs_t* import, str_list& out) { | 4664 | void transformImportAs(ImportAs_t* import, str_list& out) { |
4222 | auto x = import; | 4665 | auto x = import; |
4223 | if (!import->target) { | 4666 | if (!import->target) { |
4224 | auto name = _parser.toString(import->literal->inners.back()); | 4667 | auto name = moduleNameFrom(import->literal); |
4225 | Utils::replace(name, "-"sv, "_"sv); | ||
4226 | Utils::replace(name, " "sv, "_"sv); | ||
4227 | import->target.set(toAst<Variable_t>(name, x)); | 4668 | import->target.set(toAst<Variable_t>(name, x)); |
4228 | } | 4669 | } |
4670 | if (auto tableLit = import->target.as<TableLit_t>()) { | ||
4671 | auto newTab = x->new_ptr<TableLit_t>(); | ||
4672 | std::list<std::pair<std::string,std::string>> macroPairs; | ||
4673 | for (auto item : tableLit->values.objects()) { | ||
4674 | switch (item->getId()) { | ||
4675 | case id<MacroName_t>(): { | ||
4676 | auto macroName = static_cast<MacroName_t*>(item); | ||
4677 | auto name = _parser.toString(macroName->name); | ||
4678 | macroPairs.emplace_back(name, name); | ||
4679 | break; | ||
4680 | } | ||
4681 | case id<macro_name_pair_t>(): { | ||
4682 | auto pair = static_cast<macro_name_pair_t*>(item); | ||
4683 | macroPairs.emplace_back(_parser.toString(pair->value->name), _parser.toString(pair->key->name)); | ||
4684 | break; | ||
4685 | } | ||
4686 | default: | ||
4687 | newTab->values.push_back(item); | ||
4688 | break; | ||
4689 | } | ||
4690 | } | ||
4691 | if (!macroPairs.empty()) { | ||
4692 | auto moduleName = _parser.toString(import->literal); | ||
4693 | Utils::replace(moduleName, "'"sv, ""sv); | ||
4694 | Utils::replace(moduleName, "\""sv, ""sv); | ||
4695 | Utils::trim(moduleName); | ||
4696 | pushCurrentModule(); // cur | ||
4697 | int top = lua_gettop(L) - 1; | ||
4698 | pushMoonp("find_modulepath"sv); // cur find_modulepath | ||
4699 | lua_pushlstring(L, moduleName.c_str(), moduleName.size()); // cur find_modulepath moduleName | ||
4700 | if (lua_pcall(L, 1, 1, 0) != 0) { | ||
4701 | std::string err = lua_tostring(L, -1); | ||
4702 | lua_settop(L, top); | ||
4703 | throw std::logic_error(_info.errorMessage(s("fail to resolve module path\n"sv) + err, x)); | ||
4704 | } | ||
4705 | if (lua_isnil(L, -1) != 0) { | ||
4706 | lua_settop(L, top); | ||
4707 | throw std::logic_error(_info.errorMessage(s("fail to find module '"sv) + moduleName + '\'', x)); | ||
4708 | } | ||
4709 | std::string moduleFullName = lua_tostring(L, -1); | ||
4710 | lua_pop(L, 1); // cur | ||
4711 | if (!isModuleLoaded(moduleFullName)) { | ||
4712 | pushMoonp("read_file"sv); // cur read_file | ||
4713 | lua_pushlstring(L, moduleFullName.c_str(), moduleFullName.size()); // cur load_text moduleFullName | ||
4714 | if (lua_pcall(L, 1, 1, 0) != 0) { | ||
4715 | std::string err = lua_tostring(L, -1); | ||
4716 | lua_settop(L, top); | ||
4717 | throw std::logic_error(_info.errorMessage(s("fail to read module file\n"sv) + err, x)); | ||
4718 | } // cur text | ||
4719 | if (lua_isnil(L, -1) != 0) { | ||
4720 | lua_settop(L, top); | ||
4721 | throw std::logic_error(_info.errorMessage("fail to get module text"sv, x)); | ||
4722 | } // cur text | ||
4723 | std::string text = lua_tostring(L, -1); | ||
4724 | auto compiler = MoonCompilerImpl(L, _luaOpen, false, moduleFullName); | ||
4725 | MoonConfig config; | ||
4726 | config.lineOffset = 0; | ||
4727 | config.lintGlobalVariable = false; | ||
4728 | config.reserveLineNumber = false; | ||
4729 | config.implicitReturnRoot = _config.implicitReturnRoot; | ||
4730 | std::string codes, err; | ||
4731 | GlobalVars globals; | ||
4732 | std::tie(codes, err, globals) = compiler.compile(text, config); | ||
4733 | if (codes.empty() && !err.empty()) { | ||
4734 | lua_settop(L, top); | ||
4735 | throw std::logic_error(_info.errorMessage(s("fail to compile module '"sv) + moduleName + s("\': "sv) + err, x)); | ||
4736 | } | ||
4737 | lua_pop(L, 1); // cur | ||
4738 | } | ||
4739 | pushModuleTable(moduleFullName); // cur module | ||
4740 | for (const auto& pair : macroPairs) { | ||
4741 | lua_getfield(L, -1, pair.first.c_str()); | ||
4742 | lua_setfield(L, -3, pair.second.c_str()); | ||
4743 | } | ||
4744 | lua_settop(L, top); | ||
4745 | } | ||
4746 | if (newTab->values.empty()) { | ||
4747 | out.push_back(Empty); | ||
4748 | return; | ||
4749 | } else { | ||
4750 | import->target.set(newTab); | ||
4751 | } | ||
4752 | } | ||
4229 | auto target = import->target.get(); | 4753 | auto target = import->target.get(); |
4230 | auto value = x->new_ptr<Value_t>(); | 4754 | auto value = x->new_ptr<Value_t>(); |
4231 | if (auto var = ast_cast<Variable_t>(target)) { | 4755 | if (auto var = ast_cast<Variable_t>(target)) { |
@@ -4389,6 +4913,7 @@ private: | |||
4389 | } | 4913 | } |
4390 | 4914 | ||
4391 | void transformLocal(Local_t* local, str_list& out) { | 4915 | void transformLocal(Local_t* local, str_list& out) { |
4916 | str_list temp; | ||
4392 | if (!local->forceDecls.empty() || !local->decls.empty()) { | 4917 | if (!local->forceDecls.empty() || !local->decls.empty()) { |
4393 | str_list defs; | 4918 | str_list defs; |
4394 | for (const auto& decl : local->forceDecls) { | 4919 | for (const auto& decl : local->forceDecls) { |
@@ -4402,9 +4927,33 @@ private: | |||
4402 | } | 4927 | } |
4403 | auto preDefine = getPredefine(defs); | 4928 | auto preDefine = getPredefine(defs); |
4404 | if (!preDefine.empty()) { | 4929 | if (!preDefine.empty()) { |
4405 | out.push_back(preDefine + nll(local)); | 4930 | temp.push_back(preDefine + nll(local)); |
4931 | } | ||
4932 | } | ||
4933 | if (auto values = local->item.as<local_values_t>()) { | ||
4934 | if (values->valueList) { | ||
4935 | auto x = local; | ||
4936 | auto expList = x->new_ptr<ExpList_t>(); | ||
4937 | for (auto name : values->nameList->names.objects()) { | ||
4938 | auto callable = x->new_ptr<Callable_t>(); | ||
4939 | callable->item.set(name); | ||
4940 | auto chainValue = x->new_ptr<ChainValue_t>(); | ||
4941 | chainValue->items.push_back(callable); | ||
4942 | auto value = x->new_ptr<Value_t>(); | ||
4943 | value->item.set(chainValue); | ||
4944 | auto exp = x->new_ptr<Exp_t>(); | ||
4945 | exp->value.set(value); | ||
4946 | expList->exprs.push_back(exp); | ||
4947 | } | ||
4948 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
4949 | assignment->expList.set(expList); | ||
4950 | auto assign = x->new_ptr<Assign_t>(); | ||
4951 | assign->values.dup(values->valueList->exprs); | ||
4952 | assignment->action.set(assign); | ||
4953 | transformAssignment(assignment, temp); | ||
4406 | } | 4954 | } |
4407 | } | 4955 | } |
4956 | out.push_back(join(temp)); | ||
4408 | } | 4957 | } |
4409 | 4958 | ||
4410 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { | 4959 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { |
@@ -4413,7 +4962,7 @@ private: | |||
4413 | out.push_back(indent() + keyword + nll(breakLoop)); | 4962 | out.push_back(indent() + keyword + nll(breakLoop)); |
4414 | return; | 4963 | return; |
4415 | } | 4964 | } |
4416 | if (_continueVars.empty()) throw std::logic_error(_info.errorMessage("Continue is not inside a loop."sv, breakLoop)); | 4965 | if (_continueVars.empty()) throw std::logic_error(_info.errorMessage("continue is not inside a loop"sv, breakLoop)); |
4417 | _buf << indent() << _continueVars.top() << " = true"sv << nll(breakLoop); | 4966 | _buf << indent() << _continueVars.top() << " = true"sv << nll(breakLoop); |
4418 | _buf << indent() << "break"sv << nll(breakLoop); | 4967 | _buf << indent() << "break"sv << nll(breakLoop); |
4419 | out.push_back(clearBuf()); | 4968 | out.push_back(clearBuf()); |
@@ -4422,12 +4971,12 @@ private: | |||
4422 | 4971 | ||
4423 | const std::string MoonCompilerImpl::Empty; | 4972 | const std::string MoonCompilerImpl::Empty; |
4424 | 4973 | ||
4425 | MoonCompiler::MoonCompiler(): | 4974 | MoonCompiler::MoonCompiler(void* sharedState, |
4426 | _compiler(std::make_unique<MoonCompilerImpl>()) | 4975 | const std::function<void(void*)>& luaOpen, |
4427 | { } | 4976 | bool sameModule): |
4977 | _compiler(std::make_unique<MoonCompilerImpl>(static_cast<lua_State*>(sharedState), luaOpen, sameModule)) {} | ||
4428 | 4978 | ||
4429 | MoonCompiler::~MoonCompiler() | 4979 | MoonCompiler::~MoonCompiler() {} |
4430 | { } | ||
4431 | 4980 | ||
4432 | std::tuple<std::string,std::string,GlobalVars> MoonCompiler::compile(std::string_view codes, const MoonConfig& config) { | 4981 | std::tuple<std::string,std::string,GlobalVars> MoonCompiler::compile(std::string_view codes, const MoonConfig& config) { |
4433 | return _compiler->compile(codes, config); | 4982 | return _compiler->compile(codes, config); |