diff options
| author | Li Jin <dragon-fly@qq.com> | 2020-03-11 00:21:33 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2020-03-11 00:21:33 +0800 |
| commit | 1ee056eedf773ac6166247755439092e0e0a9bca (patch) | |
| tree | 1b8863338d37fe6ded7fbaecd92d76cdb3801ab3 /src/MoonP/moon_compiler.cpp | |
| parent | 015af4b70cd751e1c1580fd542997a796e1ca225 (diff) | |
| download | yuescript-1ee056eedf773ac6166247755439092e0e0a9bca.tar.gz yuescript-1ee056eedf773ac6166247755439092e0e0a9bca.tar.bz2 yuescript-1ee056eedf773ac6166247755439092e0e0a9bca.zip | |
add macro functions.
Diffstat (limited to 'src/MoonP/moon_compiler.cpp')
| -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); |
