aboutsummaryrefslogtreecommitdiff
path: root/src/MoonP
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2020-03-11 00:21:33 +0800
committerLi Jin <dragon-fly@qq.com>2020-03-11 00:21:33 +0800
commit1ee056eedf773ac6166247755439092e0e0a9bca (patch)
tree1b8863338d37fe6ded7fbaecd92d76cdb3801ab3 /src/MoonP
parent015af4b70cd751e1c1580fd542997a796e1ca225 (diff)
downloadyuescript-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.h62
-rw-r--r--src/MoonP/moon_compiler.cpp661
-rw-r--r--src/MoonP/moon_compiler.h6
-rw-r--r--src/MoonP/moon_parser.cpp68
-rw-r--r--src/MoonP/moon_parser.h13
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)
93AST_END(NameList) 93AST_END(NameList)
94 94
95class ExpListLow_t;
96
97AST_NODE(local_values)
98 ast_ptr<true, NameList_t> nameList;
99 ast_ptr<false, ExpListLow_t> valueList;
100 AST_MEMBER(local_values, &nameList, &valueList)
101AST_END(local_values)
102
95AST_NODE(Local) 103AST_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)
100AST_END(Local) 108AST_END(Local)
101 109
102AST_NODE(colon_import_name) 110AST_NODE(colon_import_name)
@@ -116,12 +124,6 @@ AST_NODE(ImportLiteral)
116 AST_MEMBER(ImportLiteral, &sep, &inners) 124 AST_MEMBER(ImportLiteral, &sep, &inners)
117AST_END(ImportLiteral) 125AST_END(ImportLiteral)
118 126
119AST_NODE(ImportAs)
120 ast_ptr<true, ImportLiteral_t> literal;
121 ast_sel<false, Variable_t, TableLit_t> target;
122 AST_MEMBER(ImportAs, &literal, &target)
123AST_END(ImportAs)
124
125AST_NODE(ImportFrom) 127AST_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)
130AST_END(ImportFrom) 132AST_END(ImportFrom)
131 133
134AST_NODE(ImportAs)
135 ast_ptr<true, ImportLiteral_t> literal;
136 ast_sel<false, Variable_t, TableLit_t> target;
137 AST_MEMBER(ImportAs, &literal, &target)
138AST_END(ImportAs)
139
132AST_NODE(Import) 140AST_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)
333AST_END(Exp) 341AST_END(Exp)
334 342
335class Parens_t; 343class Parens_t;
344class MacroName_t;
336 345
337AST_NODE(Callable) 346AST_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)
340AST_END(Callable) 349AST_END(Callable)
341 350
@@ -469,9 +478,15 @@ AST_END(Value)
469AST_LEAF(default_value) 478AST_LEAF(default_value)
470AST_END(default_value) 479AST_END(default_value)
471 480
481AST_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)
485AST_END(macro_name_pair)
486
472AST_NODE(TableLit) 487AST_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)
476AST_END(TableLit) 491AST_END(TableLit)
477 492
@@ -517,9 +532,11 @@ AST_END(Global)
517AST_LEAF(export_default) 532AST_LEAF(export_default)
518AST_END(export_default) 533AST_END(export_default)
519 534
535class Macro_t;
536
520AST_NODE(Export) 537AST_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)
525AST_END(Export) 542AST_END(Export)
@@ -558,6 +575,27 @@ AST_NODE(FunLit)
558 AST_MEMBER(FunLit, &argsDef, &arrow, &body) 575 AST_MEMBER(FunLit, &argsDef, &arrow, &body)
559AST_END(FunLit) 576AST_END(FunLit)
560 577
578AST_LEAF(macro_type)
579AST_END(macro_type)
580
581AST_NODE(MacroName)
582 ast_ptr<true, Name_t> name;
583 AST_MEMBER(MacroName, &name)
584AST_END(MacroName)
585
586AST_NODE(MacroLit)
587 ast_ptr<false, FnArgDefList_t> argsDef;
588 ast_ptr<true, Body_t> body;
589 AST_MEMBER(MacroLit, &argsDef, &body)
590AST_END(MacroLit)
591
592AST_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, &macroLit)
597AST_END(Macro)
598
561AST_NODE(NameOrDestructure) 599AST_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
612AST_NODE(Statement) 650AST_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
20extern "C" {
21
22#include "lua.h"
23#include "lauxlib.h"
24#include "lualib.h"
25
26} // extern "C"
27
20namespace MoonP { 28namespace MoonP {
21using namespace std::string_view_literals; 29using namespace std::string_view_literals;
22using namespace parserlib; 30using namespace parserlib;
@@ -32,11 +40,44 @@ inline std::string s(std::string_view sv) {
32} 40}
33 41
34const char* moonScriptVersion() { 42const 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
38class MoonCompilerImpl { 49class MoonCompilerImpl {
39public: 50public:
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 }
87private: 139private:
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
4423const std::string MoonCompilerImpl::Empty; 4972const std::string MoonCompilerImpl::Empty;
4424 4973
4425MoonCompiler::MoonCompiler(): 4974MoonCompiler::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
4429MoonCompiler::~MoonCompiler() 4979MoonCompiler::~MoonCompiler() {}
4430{ }
4431 4980
4432std::tuple<std::string,std::string,GlobalVars> MoonCompiler::compile(std::string_view codes, const MoonConfig& config) { 4981std::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
17namespace MoonP { 18namespace 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
27struct GlobalVar { 29struct GlobalVar {
@@ -36,7 +38,9 @@ class MoonCompilerImpl;
36 38
37class MoonCompiler { 39class MoonCompiler {
38public: 40public:
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 = {});
42private: 46private:
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
35MoonParser::MoonParser() { 35MoonParser::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
582std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc) const { 616std::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
286namespace Utils { 296namespace 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