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 | |
parent | 015af4b70cd751e1c1580fd542997a796e1ca225 (diff) | |
download | yuescript-1ee056eedf773ac6166247755439092e0e0a9bca.tar.gz yuescript-1ee056eedf773ac6166247755439092e0e0a9bca.tar.bz2 yuescript-1ee056eedf773ac6166247755439092e0e0a9bca.zip |
add macro functions.
Diffstat (limited to 'src/MoonP')
-rw-r--r-- | src/MoonP/moon_ast.h | 62 | ||||
-rw-r--r-- | src/MoonP/moon_compiler.cpp | 661 | ||||
-rw-r--r-- | src/MoonP/moon_compiler.h | 6 | ||||
-rw-r--r-- | src/MoonP/moon_parser.cpp | 68 | ||||
-rw-r--r-- | src/MoonP/moon_parser.h | 13 |
5 files changed, 723 insertions, 87 deletions
diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index 9fab215..0725bda 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h | |||
@@ -92,11 +92,19 @@ AST_NODE(NameList) | |||
92 | AST_MEMBER(NameList, &sep, &names) | 92 | AST_MEMBER(NameList, &sep, &names) |
93 | AST_END(NameList) | 93 | AST_END(NameList) |
94 | 94 | ||
95 | class ExpListLow_t; | ||
96 | |||
97 | AST_NODE(local_values) | ||
98 | ast_ptr<true, NameList_t> nameList; | ||
99 | ast_ptr<false, ExpListLow_t> valueList; | ||
100 | AST_MEMBER(local_values, &nameList, &valueList) | ||
101 | AST_END(local_values) | ||
102 | |||
95 | AST_NODE(Local) | 103 | AST_NODE(Local) |
96 | ast_sel<true, local_flag_t, NameList_t> name; | 104 | ast_sel<true, local_flag_t, local_values_t> item; |
97 | std::list<std::string> forceDecls; | 105 | std::list<std::string> forceDecls; |
98 | std::list<std::string> decls; | 106 | std::list<std::string> decls; |
99 | AST_MEMBER(Local, &name) | 107 | AST_MEMBER(Local, &item) |
100 | AST_END(Local) | 108 | AST_END(Local) |
101 | 109 | ||
102 | AST_NODE(colon_import_name) | 110 | AST_NODE(colon_import_name) |
@@ -116,12 +124,6 @@ AST_NODE(ImportLiteral) | |||
116 | AST_MEMBER(ImportLiteral, &sep, &inners) | 124 | AST_MEMBER(ImportLiteral, &sep, &inners) |
117 | AST_END(ImportLiteral) | 125 | AST_END(ImportLiteral) |
118 | 126 | ||
119 | AST_NODE(ImportAs) | ||
120 | ast_ptr<true, ImportLiteral_t> literal; | ||
121 | ast_sel<false, Variable_t, TableLit_t> target; | ||
122 | AST_MEMBER(ImportAs, &literal, &target) | ||
123 | AST_END(ImportAs) | ||
124 | |||
125 | AST_NODE(ImportFrom) | 127 | AST_NODE(ImportFrom) |
126 | ast_ptr<true, Seperator_t> sep; | 128 | ast_ptr<true, Seperator_t> sep; |
127 | ast_sel_list<true, colon_import_name_t, Variable_t> names; | 129 | ast_sel_list<true, colon_import_name_t, Variable_t> names; |
@@ -129,6 +131,12 @@ AST_NODE(ImportFrom) | |||
129 | AST_MEMBER(ImportFrom, &sep, &names, &exp) | 131 | AST_MEMBER(ImportFrom, &sep, &names, &exp) |
130 | AST_END(ImportFrom) | 132 | AST_END(ImportFrom) |
131 | 133 | ||
134 | AST_NODE(ImportAs) | ||
135 | ast_ptr<true, ImportLiteral_t> literal; | ||
136 | ast_sel<false, Variable_t, TableLit_t> target; | ||
137 | AST_MEMBER(ImportAs, &literal, &target) | ||
138 | AST_END(ImportAs) | ||
139 | |||
132 | AST_NODE(Import) | 140 | AST_NODE(Import) |
133 | ast_sel<true, ImportAs_t, ImportFrom_t> content; | 141 | ast_sel<true, ImportAs_t, ImportFrom_t> content; |
134 | AST_MEMBER(Import, &content) | 142 | AST_MEMBER(Import, &content) |
@@ -333,9 +341,10 @@ AST_NODE(Exp) | |||
333 | AST_END(Exp) | 341 | AST_END(Exp) |
334 | 342 | ||
335 | class Parens_t; | 343 | class Parens_t; |
344 | class MacroName_t; | ||
336 | 345 | ||
337 | AST_NODE(Callable) | 346 | AST_NODE(Callable) |
338 | ast_sel<true, Variable_t, SelfName_t, VarArg_t, Parens_t> item; | 347 | ast_sel<true, Variable_t, SelfName_t, VarArg_t, Parens_t, MacroName_t> item; |
339 | AST_MEMBER(Callable, &item) | 348 | AST_MEMBER(Callable, &item) |
340 | AST_END(Callable) | 349 | AST_END(Callable) |
341 | 350 | ||
@@ -469,9 +478,15 @@ AST_END(Value) | |||
469 | AST_LEAF(default_value) | 478 | AST_LEAF(default_value) |
470 | AST_END(default_value) | 479 | AST_END(default_value) |
471 | 480 | ||
481 | AST_NODE(macro_name_pair) | ||
482 | ast_ptr<true, MacroName_t> key; | ||
483 | ast_ptr<true, MacroName_t> value; | ||
484 | AST_MEMBER(macro_name_pair, &key, &value) | ||
485 | AST_END(macro_name_pair) | ||
486 | |||
472 | AST_NODE(TableLit) | 487 | AST_NODE(TableLit) |
473 | ast_ptr<true, Seperator_t> sep; | 488 | ast_ptr<true, Seperator_t> sep; |
474 | ast_sel_list<false, variable_pair_t, normal_pair_t, Exp_t> values; | 489 | ast_sel_list<false, variable_pair_t, normal_pair_t, Exp_t, MacroName_t, macro_name_pair_t> values; |
475 | AST_MEMBER(TableLit, &sep, &values) | 490 | AST_MEMBER(TableLit, &sep, &values) |
476 | AST_END(TableLit) | 491 | AST_END(TableLit) |
477 | 492 | ||
@@ -517,9 +532,11 @@ AST_END(Global) | |||
517 | AST_LEAF(export_default) | 532 | AST_LEAF(export_default) |
518 | AST_END(export_default) | 533 | AST_END(export_default) |
519 | 534 | ||
535 | class Macro_t; | ||
536 | |||
520 | AST_NODE(Export) | 537 | AST_NODE(Export) |
521 | ast_ptr<false, export_default_t> def; | 538 | ast_ptr<false, export_default_t> def; |
522 | ast_sel<true, ExpList_t, Exp_t> target; | 539 | ast_sel<true, ExpList_t, Exp_t, Macro_t> target; |
523 | ast_ptr<false, Assign_t> assign; | 540 | ast_ptr<false, Assign_t> assign; |
524 | AST_MEMBER(Export, &def, &target, &assign) | 541 | AST_MEMBER(Export, &def, &target, &assign) |
525 | AST_END(Export) | 542 | AST_END(Export) |
@@ -558,6 +575,27 @@ AST_NODE(FunLit) | |||
558 | AST_MEMBER(FunLit, &argsDef, &arrow, &body) | 575 | AST_MEMBER(FunLit, &argsDef, &arrow, &body) |
559 | AST_END(FunLit) | 576 | AST_END(FunLit) |
560 | 577 | ||
578 | AST_LEAF(macro_type) | ||
579 | AST_END(macro_type) | ||
580 | |||
581 | AST_NODE(MacroName) | ||
582 | ast_ptr<true, Name_t> name; | ||
583 | AST_MEMBER(MacroName, &name) | ||
584 | AST_END(MacroName) | ||
585 | |||
586 | AST_NODE(MacroLit) | ||
587 | ast_ptr<false, FnArgDefList_t> argsDef; | ||
588 | ast_ptr<true, Body_t> body; | ||
589 | AST_MEMBER(MacroLit, &argsDef, &body) | ||
590 | AST_END(MacroLit) | ||
591 | |||
592 | AST_NODE(Macro) | ||
593 | ast_ptr<true, macro_type_t> type; | ||
594 | ast_ptr<true, Name_t> name; | ||
595 | ast_ptr<true, MacroLit_t> macroLit; | ||
596 | AST_MEMBER(Macro, &type, &name, ¯oLit) | ||
597 | AST_END(Macro) | ||
598 | |||
561 | AST_NODE(NameOrDestructure) | 599 | AST_NODE(NameOrDestructure) |
562 | ast_sel<true, Variable_t, TableLit_t> item; | 600 | ast_sel<true, Variable_t, TableLit_t> item; |
563 | AST_MEMBER(NameOrDestructure, &item) | 601 | AST_MEMBER(NameOrDestructure, &item) |
@@ -611,7 +649,7 @@ AST_END(BreakLoop) | |||
611 | 649 | ||
612 | AST_NODE(Statement) | 650 | AST_NODE(Statement) |
613 | ast_sel<true, Import_t, While_t, For_t, ForEach_t, | 651 | ast_sel<true, Import_t, While_t, For_t, ForEach_t, |
614 | Return_t, Local_t, Global_t, Export_t, BreakLoop_t, | 652 | Return_t, Local_t, Global_t, Export_t, Macro_t, BreakLoop_t, |
615 | Backcall_t, ExpListAssign_t> content; | 653 | Backcall_t, ExpListAssign_t> content; |
616 | ast_ptr<false, statement_appendix_t> appendix; | 654 | ast_ptr<false, statement_appendix_t> appendix; |
617 | AST_MEMBER(Statement, &content, &appendix) | 655 | AST_MEMBER(Statement, &content, &appendix) |
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); |
diff --git a/src/MoonP/moon_compiler.h b/src/MoonP/moon_compiler.h index 36fd77a..573f130 100644 --- a/src/MoonP/moon_compiler.h +++ b/src/MoonP/moon_compiler.h | |||
@@ -13,6 +13,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
13 | #include <tuple> | 13 | #include <tuple> |
14 | #include <list> | 14 | #include <list> |
15 | #include <memory> | 15 | #include <memory> |
16 | #include <functional> | ||
16 | 17 | ||
17 | namespace MoonP { | 18 | namespace MoonP { |
18 | 19 | ||
@@ -22,6 +23,7 @@ struct MoonConfig { | |||
22 | bool lintGlobalVariable = false; | 23 | bool lintGlobalVariable = false; |
23 | bool implicitReturnRoot = true; | 24 | bool implicitReturnRoot = true; |
24 | bool reserveLineNumber = true; | 25 | bool reserveLineNumber = true; |
26 | int lineOffset = 0; | ||
25 | }; | 27 | }; |
26 | 28 | ||
27 | struct GlobalVar { | 29 | struct GlobalVar { |
@@ -36,7 +38,9 @@ class MoonCompilerImpl; | |||
36 | 38 | ||
37 | class MoonCompiler { | 39 | class MoonCompiler { |
38 | public: | 40 | public: |
39 | MoonCompiler(); | 41 | MoonCompiler(void* luaState = nullptr, |
42 | const std::function<void(void*)>& luaOpen = nullptr, | ||
43 | bool sameModule = false); | ||
40 | virtual ~MoonCompiler(); | 44 | virtual ~MoonCompiler(); |
41 | std::tuple<std::string,std::string,GlobalVars> compile(std::string_view codes, const MoonConfig& config = {}); | 45 | std::tuple<std::string,std::string,GlobalVars> compile(std::string_view codes, const MoonConfig& config = {}); |
42 | private: | 46 | private: |
diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index baa8eff..f0269d7 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp | |||
@@ -28,8 +28,8 @@ std::unordered_set<std::string> Keywords = { | |||
28 | "repeat", "return", "then", "true", "until", | 28 | "repeat", "return", "then", "true", "until", |
29 | "while", // Lua keywords | 29 | "while", // Lua keywords |
30 | "as", "class", "continue", "export", "extends", | 30 | "as", "class", "continue", "export", "extends", |
31 | "from", "global", "import", "switch", "unless", | 31 | "from", "global", "import", "macro", "switch", |
32 | "using", "when", "with" // Moon keywords | 32 | "unless", "using", "when", "with" // Moon keywords |
33 | }; | 33 | }; |
34 | 34 | ||
35 | MoonParser::MoonParser() { | 35 | MoonParser::MoonParser() { |
@@ -98,9 +98,9 @@ MoonParser::MoonParser() { | |||
98 | self_class = expr("@@"); | 98 | self_class = expr("@@"); |
99 | self_class_name = "@@" >> Name; | 99 | self_class_name = "@@" >> Name; |
100 | 100 | ||
101 | SelfName = Space >> (self_class_name | self_class | self_name | self); | 101 | SelfName = self_class_name | self_class | self_name | self; |
102 | KeyName = SelfName | Space >> Name; | 102 | KeyName = Space >> (SelfName | Name); |
103 | VarArg = Space >> "..."; | 103 | VarArg = expr("..."); |
104 | 104 | ||
105 | check_indent = pl::user(Indent, [](const item_t& item) { | 105 | check_indent = pl::user(Indent, [](const item_t& item) { |
106 | int indent = 0; | 106 | int indent = 0; |
@@ -162,7 +162,8 @@ MoonParser::MoonParser() { | |||
162 | InBlock = Advance >> ensure(Block, PopIndent); | 162 | InBlock = Advance >> ensure(Block, PopIndent); |
163 | 163 | ||
164 | local_flag = expr('*') | expr('^'); | 164 | local_flag = expr('*') | expr('^'); |
165 | Local = key("local") >> ((Space >> local_flag) | NameList); | 165 | local_values = NameList >> -(sym('=') >> ExpListLow); |
166 | Local = key("local") >> (Space >> local_flag | local_values); | ||
166 | 167 | ||
167 | colon_import_name = sym('\\') >> Space >> Variable; | 168 | colon_import_name = sym('\\') >> Space >> Variable; |
168 | ImportName = colon_import_name | Space >> Variable; | 169 | ImportName = colon_import_name | Space >> Variable; |
@@ -173,9 +174,23 @@ MoonParser::MoonParser() { | |||
173 | ImportLiteral = sym('\'') >> import_literal_chain >> symx('\'') | sym('"') >> import_literal_chain >> symx('"'); | 174 | ImportLiteral = sym('\'') >> import_literal_chain >> symx('\'') | sym('"') >> import_literal_chain >> symx('"'); |
174 | 175 | ||
175 | ImportFrom = ImportNameList >> *SpaceBreak >> key("from") >> Exp; | 176 | ImportFrom = ImportNameList >> *SpaceBreak >> key("from") >> Exp; |
176 | ImportAs = ImportLiteral >> -(key("as") >> (Space >> Variable | TableLit)); | 177 | |
178 | EnableMacroPair = pl::user(true_(), [](const item_t& item) { | ||
179 | State* st = reinterpret_cast<State*>(item.user_data); | ||
180 | st->macroPairEnabled = true; | ||
181 | return true; | ||
182 | }); | ||
183 | |||
184 | DiableMacroPair = pl::user(true_(), [](const item_t& item) { | ||
185 | State* st = reinterpret_cast<State*>(item.user_data); | ||
186 | st->macroPairEnabled = false; | ||
187 | return true; | ||
188 | }); | ||
189 | |||
190 | ImportAs = ImportLiteral >> -(key("as") >> (Space >> Variable | EnableMacroPair >> ensure(TableLit, DiableMacroPair))); | ||
177 | 191 | ||
178 | Import = key("import") >> (ImportAs | ImportFrom); | 192 | Import = key("import") >> (ImportAs | ImportFrom); |
193 | |||
179 | BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); | 194 | BreakLoop = (expr("break") | expr("continue")) >> not_(AlphaNum); |
180 | 195 | ||
181 | Return = key("return") >> -ExpListLow; | 196 | Return = key("return") >> -ExpListLow; |
@@ -278,7 +293,7 @@ MoonParser::MoonParser() { | |||
278 | 293 | ||
279 | BackcallOperator = expr("|>"); | 294 | BackcallOperator = expr("|>"); |
280 | 295 | ||
281 | Assignable = AssignableChain | Space >> Variable | SelfName; | 296 | Assignable = AssignableChain | Space >> Variable | Space >> SelfName; |
282 | 297 | ||
283 | exp_op_value = Space >> (BackcallOperator | BinaryOperator) >> *SpaceBreak >> Value; | 298 | exp_op_value = Space >> (BackcallOperator | BinaryOperator) >> *SpaceBreak >> Value; |
284 | Exp = Value >> *exp_op_value; | 299 | Exp = Value >> *exp_op_value; |
@@ -317,8 +332,8 @@ MoonParser::MoonParser() { | |||
317 | 332 | ||
318 | LuaString = LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose; | 333 | LuaString = LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose; |
319 | 334 | ||
320 | Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); | 335 | Parens = symx('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); |
321 | Callable = Space >> Variable | SelfName | VarArg | Parens; | 336 | Callable = Space >> (Variable | SelfName | MacroName | VarArg | Parens); |
322 | FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); | 337 | FnArgsExpList = Exp >> *((Break | sym(',')) >> White >> Exp); |
323 | 338 | ||
324 | FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | | 339 | FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | |
@@ -414,7 +429,8 @@ MoonParser::MoonParser() { | |||
414 | } else { | 429 | } else { |
415 | return true; | 430 | return true; |
416 | } | 431 | } |
417 | }) >> ExpList >> -Assign)) >> not_(Space >> statement_appendix); | 432 | }) >> ExpList >> -Assign) |
433 | | Macro) >> not_(Space >> statement_appendix); | ||
418 | 434 | ||
419 | variable_pair = sym(':') >> Variable; | 435 | variable_pair = sym(':') >> Variable; |
420 | 436 | ||
@@ -427,14 +443,19 @@ MoonParser::MoonParser() { | |||
427 | symx(':') >> | 443 | symx(':') >> |
428 | (Exp | TableBlock | +(SpaceBreak) >> Exp); | 444 | (Exp | TableBlock | +(SpaceBreak) >> Exp); |
429 | 445 | ||
430 | KeyValue = variable_pair | normal_pair; | 446 | macro_name_pair = Space >> MacroName >> Space >> symx(':') >> Space >> MacroName; |
447 | |||
448 | KeyValue = variable_pair | normal_pair | pl::user(sym(':') >> MacroName | macro_name_pair, [](const item_t& item) { | ||
449 | State* st = reinterpret_cast<State*>(item.user_data); | ||
450 | return st->macroPairEnabled; | ||
451 | }); | ||
431 | 452 | ||
432 | KeyValueList = KeyValue >> *(sym(',') >> KeyValue); | 453 | KeyValueList = KeyValue >> *(sym(',') >> KeyValue); |
433 | KeyValueLine = CheckIndent >> KeyValueList >> -sym(','); | 454 | KeyValueLine = CheckIndent >> KeyValueList >> -sym(','); |
434 | 455 | ||
435 | FnArgDef = (Space >> Variable | SelfName) >> -(sym('=') >> Exp); | 456 | FnArgDef = (Variable | SelfName) >> -(sym('=') >> Space >> Exp); |
436 | 457 | ||
437 | FnArgDefList = Seperator >> ( | 458 | FnArgDefList = Space >> Seperator >> ( |
438 | ( | 459 | ( |
439 | FnArgDef >> | 460 | FnArgDef >> |
440 | *((sym(',') | Break) >> White >> FnArgDef) >> | 461 | *((sym(',') | Break) >> White >> FnArgDef) >> |
@@ -450,6 +471,12 @@ MoonParser::MoonParser() { | |||
450 | fn_arrow = expr("->") | expr("=>"); | 471 | fn_arrow = expr("->") | expr("=>"); |
451 | FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; | 472 | FunLit = -FnArgsDef >> Space >> fn_arrow >> -Body; |
452 | 473 | ||
474 | MacroName = expr('$') >> Name; | ||
475 | macro_type = expr("expr") | expr("block"); | ||
476 | macro_args_def = sym('(') >> White >> -FnArgDefList >> White >> sym(')'); | ||
477 | MacroLit = -macro_args_def >> Space >> expr("->") >> Body; | ||
478 | Macro = key("macro") >> Space >> macro_type >> Space >> Name >> sym('=') >> MacroLit; | ||
479 | |||
453 | NameList = Seperator >> Space >> Variable >> *(sym(',') >> White >> Variable); | 480 | NameList = Seperator >> Space >> Variable >> *(sym(',') >> White >> Variable); |
454 | NameOrDestructure = Space >> Variable | TableLit; | 481 | NameOrDestructure = Space >> Variable | TableLit; |
455 | AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> White >> NameOrDestructure); | 482 | AssignableNameList = Seperator >> NameOrDestructure >> *(sym(',') >> White >> NameOrDestructure); |
@@ -499,7 +526,8 @@ MoonParser::MoonParser() { | |||
499 | statement_appendix = (if_else_line | unless_line | CompInner) >> Space; | 526 | statement_appendix = (if_else_line | unless_line | CompInner) >> Space; |
500 | Statement = ( | 527 | Statement = ( |
501 | Import | While | For | ForEach | | 528 | Import | While | For | ForEach | |
502 | Return | Local | Global | Export | Space >> BreakLoop | | 529 | Return | Local | Global | Export | |
530 | Macro | Space >> BreakLoop | | ||
503 | Backcall | ExpListAssign | 531 | Backcall | ExpListAssign |
504 | ) >> Space >> | 532 | ) >> Space >> |
505 | -statement_appendix; | 533 | -statement_appendix; |
@@ -541,10 +569,10 @@ ParseInfo MoonParser::parse(std::string_view codes, rule& r) { | |||
541 | const error& err = *it; | 569 | const error& err = *it; |
542 | switch (err.m_type) { | 570 | switch (err.m_type) { |
543 | case ERROR_TYPE::ERROR_SYNTAX_ERROR: | 571 | case ERROR_TYPE::ERROR_SYNTAX_ERROR: |
544 | buf << res.errorMessage("Syntax error."sv, &err); | 572 | buf << res.errorMessage("syntax error"sv, &err); |
545 | break; | 573 | break; |
546 | case ERROR_TYPE::ERROR_INVALID_EOF: | 574 | case ERROR_TYPE::ERROR_INVALID_EOF: |
547 | buf << res.errorMessage("Invalid EOF."sv, &err); | 575 | buf << res.errorMessage("invalid EOF"sv, &err); |
548 | break; | 576 | break; |
549 | } | 577 | } |
550 | } | 578 | } |
@@ -577,6 +605,12 @@ namespace Utils { | |||
577 | start_pos += to.size(); | 605 | start_pos += to.size(); |
578 | } | 606 | } |
579 | } | 607 | } |
608 | |||
609 | void trim(std::string& str) { | ||
610 | if (str.empty()) return; | ||
611 | str.erase(0, str.find_first_not_of(" \t")); | ||
612 | str.erase(str.find_last_not_of(" \t") + 1); | ||
613 | } | ||
580 | } | 614 | } |
581 | 615 | ||
582 | std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc) const { | 616 | std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc) const { |
diff --git a/src/MoonP/moon_parser.h b/src/MoonP/moon_parser.h index eefcba5..4d67696 100644 --- a/src/MoonP/moon_parser.h +++ b/src/MoonP/moon_parser.h | |||
@@ -12,7 +12,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
12 | #include <unordered_set> | 12 | #include <unordered_set> |
13 | #include <stack> | 13 | #include <stack> |
14 | #include <algorithm> | 14 | #include <algorithm> |
15 | #include <vector> | 15 | #include <list> |
16 | #include <sstream> | 16 | #include <sstream> |
17 | #include <string_view> | 17 | #include <string_view> |
18 | 18 | ||
@@ -75,6 +75,7 @@ protected: | |||
75 | State() { | 75 | State() { |
76 | indents.push(0); | 76 | indents.push(0); |
77 | } | 77 | } |
78 | bool macroPairEnabled = false; | ||
78 | bool exportDefault = false; | 79 | bool exportDefault = false; |
79 | int exportCount = 0; | 80 | int exportCount = 0; |
80 | int moduleFix = 0; | 81 | int moduleFix = 0; |
@@ -131,6 +132,8 @@ private: | |||
131 | rule WithExp; | 132 | rule WithExp; |
132 | rule DisableDo; | 133 | rule DisableDo; |
133 | rule PopDo; | 134 | rule PopDo; |
135 | rule EnableMacroPair; | ||
136 | rule DiableMacroPair; | ||
134 | rule SwitchElse; | 137 | rule SwitchElse; |
135 | rule SwitchBlock; | 138 | rule SwitchBlock; |
136 | rule IfElseIf; | 139 | rule IfElseIf; |
@@ -147,6 +150,7 @@ private: | |||
147 | rule lua_string_close; | 150 | rule lua_string_close; |
148 | rule FnArgsExpList; | 151 | rule FnArgsExpList; |
149 | rule FnArgs; | 152 | rule FnArgs; |
153 | rule macro_args_def; | ||
150 | rule chain_call; | 154 | rule chain_call; |
151 | rule chain_item; | 155 | rule chain_item; |
152 | rule ChainItems; | 156 | rule ChainItems; |
@@ -189,6 +193,7 @@ private: | |||
189 | AST_RULE(Seperator) | 193 | AST_RULE(Seperator) |
190 | AST_RULE(NameList) | 194 | AST_RULE(NameList) |
191 | AST_RULE(local_flag) | 195 | AST_RULE(local_flag) |
196 | AST_RULE(local_values) | ||
192 | AST_RULE(Local) | 197 | AST_RULE(Local) |
193 | AST_RULE(colon_import_name) | 198 | AST_RULE(colon_import_name) |
194 | AST_RULE(import_literal_inner) | 199 | AST_RULE(import_literal_inner) |
@@ -261,12 +266,17 @@ private: | |||
261 | AST_RULE(Export) | 266 | AST_RULE(Export) |
262 | AST_RULE(variable_pair) | 267 | AST_RULE(variable_pair) |
263 | AST_RULE(normal_pair) | 268 | AST_RULE(normal_pair) |
269 | AST_RULE(macro_name_pair) | ||
264 | AST_RULE(FnArgDef) | 270 | AST_RULE(FnArgDef) |
265 | AST_RULE(FnArgDefList) | 271 | AST_RULE(FnArgDefList) |
266 | AST_RULE(outer_var_shadow) | 272 | AST_RULE(outer_var_shadow) |
267 | AST_RULE(FnArgsDef) | 273 | AST_RULE(FnArgsDef) |
268 | AST_RULE(fn_arrow) | 274 | AST_RULE(fn_arrow) |
269 | AST_RULE(FunLit) | 275 | AST_RULE(FunLit) |
276 | AST_RULE(macro_type) | ||
277 | AST_RULE(MacroName) | ||
278 | AST_RULE(MacroLit) | ||
279 | AST_RULE(Macro) | ||
270 | AST_RULE(NameOrDestructure) | 280 | AST_RULE(NameOrDestructure) |
271 | AST_RULE(AssignableNameList) | 281 | AST_RULE(AssignableNameList) |
272 | AST_RULE(InvokeArgs) | 282 | AST_RULE(InvokeArgs) |
@@ -285,6 +295,7 @@ private: | |||
285 | 295 | ||
286 | namespace Utils { | 296 | namespace Utils { |
287 | void replace(std::string& str, std::string_view from, std::string_view to); | 297 | void replace(std::string& str, std::string_view from, std::string_view to); |
298 | void trim(std::string& str); | ||
288 | }; | 299 | }; |
289 | 300 | ||
290 | } // namespace MoonP | 301 | } // namespace MoonP |