aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2020-02-03 15:44:20 +0800
committerLi Jin <dragon-fly@qq.com>2020-02-03 15:44:20 +0800
commitd75848152e337fc9d3a4041ec310fea07476c0a8 (patch)
tree22e74a062b8eaff1fd99f002c473ccdfd5181157
parentd8901102a1e39e651b08b66257c176b5803b9bc0 (diff)
downloadyuescript-d75848152e337fc9d3a4041ec310fea07476c0a8.tar.gz
yuescript-d75848152e337fc9d3a4041ec310fea07476c0a8.tar.bz2
yuescript-d75848152e337fc9d3a4041ec310fea07476c0a8.zip
fix some cases when using backcall with assignment.
-rw-r--r--.gitignore2
-rw-r--r--README.md5
-rw-r--r--makefile4
-rw-r--r--spec/inputs/assign.moon4
-rw-r--r--spec/inputs/backcall.moon10
-rw-r--r--src/MoonP/moon_compiler.cpp260
-rw-r--r--src/MoonP/moon_parser.h1
7 files changed, 137 insertions, 149 deletions
diff --git a/.gitignore b/.gitignore
index 970c771..5f6a200 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
1moonc 1moonp
2build 2build
3spec/outputs 3spec/outputs
diff --git a/README.md b/README.md
index b4b5be3..018e6b0 100644
--- a/README.md
+++ b/README.md
@@ -182,10 +182,11 @@ end
182## Standalone Compiler Usage 182## Standalone Compiler Usage
183 183
184Test compiler with `make test`. 184Test compiler with `make test`.
185Run `moonc` complier in project folder with: 185Run `moonp` complier in project folder with:
186
186```shell 187```shell
187make 188make
188./moonc -h 189./moonp -h
189``` 190```
190 191
191## License 192## License
diff --git a/makefile b/makefile
index 77a23fc..fd2d718 100644
--- a/makefile
+++ b/makefile
@@ -1,6 +1,6 @@
1#### PROJECT SETTINGS #### 1#### PROJECT SETTINGS ####
2# The name of the executable to be created 2# The name of the executable to be created
3BIN_NAME := moonc 3BIN_NAME := moonp
4# Compiler used 4# Compiler used
5CXX ?= g++ 5CXX ?= g++
6# Extension of source files used in the project 6# Extension of source files used in the project
@@ -206,7 +206,7 @@ clean:
206.PHONY: test 206.PHONY: test
207test: release 207test: release
208 @echo "Compiling Moonscript codes..." 208 @echo "Compiling Moonscript codes..."
209 @./$(BIN_NAME) $(TEST_INPUT)/*.moon -l -t $(TEST_OUTPUT) 209 @./$(BIN_NAME) $(TEST_INPUT)/*.moon -t $(TEST_OUTPUT)
210 210
211# Main rule, checks the executable and symlinks to the output 211# Main rule, checks the executable and symlinks to the output
212all: $(BIN_PATH)/$(BIN_NAME) 212all: $(BIN_PATH)/$(BIN_NAME)
diff --git a/spec/inputs/assign.moon b/spec/inputs/assign.moon
index e8fcbfd..dac2ba3 100644
--- a/spec/inputs/assign.moon
+++ b/spec/inputs/assign.moon
@@ -27,3 +27,7 @@ else
27 "nothing", "yeah" 27 "nothing", "yeah"
28 28
29c, d = 1, 2 if true 29c, d = 1, 2 if true
30
31x = (do
32 f!
33 123) if f = getHandler!
diff --git a/spec/inputs/backcall.moon b/spec/inputs/backcall.moon
index 7702059..c52fee3 100644
--- a/spec/inputs/backcall.moon
+++ b/spec/inputs/backcall.moon
@@ -58,4 +58,14 @@ do
58 <- f6 58 <- f6
59 f7! 59 f7!
60 60
61do
62 result = do
63 (data)<- loadAsync "filename.txt"
64 print data
65 print result
66
67 totalSize = (for file in *files
68 (data)<-loadAsync file
69 addToCache file,data) |> reduce 0,(a,b)-> a+b
70
61alert "hi" 71alert "hi"
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp
index f74d056..d3427d3 100644
--- a/src/MoonP/moon_compiler.cpp
+++ b/src/MoonP/moon_compiler.cpp
@@ -42,7 +42,7 @@ public:
42 try { 42 try {
43 str_list out; 43 str_list out;
44 pushScope(); 44 pushScope();
45 transformBlock(_info.node.to<File_t>()->block, out, config.implicitReturnRoot); 45 transformBlock(_info.node.to<File_t>()->block, out, config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common);
46 popScope(); 46 popScope();
47 if (config.lintGlobalVariable) { 47 if (config.lintGlobalVariable) {
48 globals = std::make_unique<std::list<GlobalVar>>(); 48 globals = std::make_unique<std::list<GlobalVar>>();
@@ -664,12 +664,12 @@ private:
664 case "If"_id: transformIf(static_cast<If_t*>(value), out, ExpUsage::Common); break; 664 case "If"_id: transformIf(static_cast<If_t*>(value), out, ExpUsage::Common); break;
665 case "ClassDecl"_id: transformClassDecl(static_cast<ClassDecl_t*>(value), out, ExpUsage::Common); break; 665 case "ClassDecl"_id: transformClassDecl(static_cast<ClassDecl_t*>(value), out, ExpUsage::Common); break;
666 case "Unless"_id: transformUnless(static_cast<Unless_t*>(value), out, ExpUsage::Common); break; 666 case "Unless"_id: transformUnless(static_cast<Unless_t*>(value), out, ExpUsage::Common); break;
667 case "Switch"_id: transformSwitch(static_cast<Switch_t*>(value), out); break; 667 case "Switch"_id: transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Common); break;
668 case "With"_id: transformWith(static_cast<With_t*>(value), out); break; 668 case "With"_id: transformWith(static_cast<With_t*>(value), out); break;
669 case "ForEach"_id: transformForEach(static_cast<ForEach_t*>(value), out); break; 669 case "ForEach"_id: transformForEach(static_cast<ForEach_t*>(value), out); break;
670 case "For"_id: transformFor(static_cast<For_t*>(value), out); break; 670 case "For"_id: transformFor(static_cast<For_t*>(value), out); break;
671 case "While"_id: transformWhile(static_cast<While_t*>(value), out); break; 671 case "While"_id: transformWhile(static_cast<While_t*>(value), out); break;
672 case "Do"_id: transformDo(static_cast<Do_t*>(value), out); break; 672 case "Do"_id: transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break;
673 case "Comprehension"_id: transformCompCommon(static_cast<Comprehension_t*>(value), out); break; 673 case "Comprehension"_id: transformCompCommon(static_cast<Comprehension_t*>(value), out); break;
674 default: specialSingleValue = false; break; 674 default: specialSingleValue = false; break;
675 } 675 }
@@ -822,31 +822,6 @@ private:
822 return nullptr; 822 return nullptr;
823 } 823 }
824 824
825 void assignLastExplist(ExpList_t* expList, Body_t* body) {
826 auto last = lastStatementFrom(body);
827 if (!last) return;
828 bool lastAssignable = expListFrom(last) || ast_is<For_t, ForEach_t, While_t>(last->content);
829 if (lastAssignable) {
830 auto x = last;
831 auto newAssignment = x->new_ptr<ExpListAssign_t>();
832 newAssignment->expList.set(expList);
833 auto assign = x->new_ptr<Assign_t>();
834 if (auto valueList = last->content.as<ExpListAssign_t>()) {
835 assign->values.dup(valueList->expList->exprs);
836 } else {
837 auto simpleValue = x->new_ptr<SimpleValue_t>();
838 simpleValue->value.set(last->content);
839 auto value = x->new_ptr<Value_t>();
840 value->item.set(simpleValue);
841 auto exp = x->new_ptr<Exp_t>();
842 exp->value.set(value);
843 assign->values.push_back(exp);
844 }
845 newAssignment->action.set(assign);
846 last->content.set(newAssignment);
847 }
848 }
849
850 void transformAssignment(ExpListAssign_t* assignment, str_list& out) { 825 void transformAssignment(ExpListAssign_t* assignment, str_list& out) {
851 checkAssignable(assignment->expList); 826 checkAssignable(assignment->expList);
852 BLOCK_START 827 BLOCK_START
@@ -865,36 +840,18 @@ private:
865 str_list temp; 840 str_list temp;
866 auto defs = transformAssignDefs(expList); 841 auto defs = transformAssignDefs(expList);
867 if (!defs.empty()) temp.push_back(getPredefine(defs) + nll(expList)); 842 if (!defs.empty()) temp.push_back(getPredefine(defs) + nll(expList));
868 value->traverse([&](ast_node* node) {
869 switch (node->getId()) {
870 case "IfCond"_id: return traversal::Return;
871 case "Body"_id: {
872 auto body = static_cast<Body_t*>(node);
873 assignLastExplist(expList, body);
874 return traversal::Return;
875 }
876 default: return traversal::Continue;
877 }
878 });
879 switch (value->getId()) { 843 switch (value->getId()) {
880 case "If"_id: transformIf(static_cast<If_t*>(value), temp, ExpUsage::Common); break; 844 case "If"_id: transformIf(static_cast<If_t*>(value), temp, ExpUsage::Assignment, expList); break;
881 case "Unless"_id: transformUnless(static_cast<Unless_t*>(value), temp, ExpUsage::Common); break; 845 case "Unless"_id: transformUnless(static_cast<Unless_t*>(value), temp, ExpUsage::Assignment, expList); break;
882 } 846 }
883 out.push_back(join(temp)); 847 out.push_back(join(temp));
884 return; 848 return;
885 } 849 }
886 case "Switch"_id: { 850 case "Switch"_id: {
887 auto switchNode = static_cast<Switch_t*>(value); 851 auto switchNode = static_cast<Switch_t*>(value);
888 auto expList = assignment->expList.get(); 852 auto assignList = assignment->expList.get();
889 for (auto branch_ : switchNode->branches.objects()) {
890 auto branch = static_cast<SwitchCase_t*>(branch_);
891 assignLastExplist(expList, branch->body);
892 }
893 if (switchNode->lastBranch) {
894 assignLastExplist(expList, switchNode->lastBranch);
895 }
896 std::string preDefine = getPredefine(assignment); 853 std::string preDefine = getPredefine(assignment);
897 transformSwitch(switchNode, out); 854 transformSwitch(switchNode, out, ExpUsage::Assignment, assignList);
898 out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); 855 out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment));
899 return; 856 return;
900 } 857 }
@@ -909,9 +866,8 @@ private:
909 case "Do"_id: { 866 case "Do"_id: {
910 auto expList = assignment->expList.get(); 867 auto expList = assignment->expList.get();
911 auto doNode = static_cast<Do_t*>(value); 868 auto doNode = static_cast<Do_t*>(value);
912 assignLastExplist(expList, doNode->body);
913 std::string preDefine = getPredefine(assignment); 869 std::string preDefine = getPredefine(assignment);
914 transformDo(doNode, out); 870 transformDo(doNode, out, ExpUsage::Assignment, expList);
915 out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment)); 871 out.back().insert(0, preDefine.empty() ? Empty : preDefine + nll(assignment));
916 return; 872 return;
917 } 873 }
@@ -1052,7 +1008,7 @@ private:
1052 switch (value->getId()) { 1008 switch (value->getId()) {
1053 case "With"_id: transformWithClosure(static_cast<With_t*>(value), out); break; 1009 case "With"_id: transformWithClosure(static_cast<With_t*>(value), out); break;
1054 case "If"_id: transformIf(static_cast<If_t*>(value), out, ExpUsage::Closure); break; 1010 case "If"_id: transformIf(static_cast<If_t*>(value), out, ExpUsage::Closure); break;
1055 case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break; 1011 case "Switch"_id: transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Closure); break;
1056 case "TableBlock"_id: transformTableBlock(static_cast<TableBlock_t*>(value), out); break; 1012 case "TableBlock"_id: transformTableBlock(static_cast<TableBlock_t*>(value), out); break;
1057 case "Exp"_id: transformExp(static_cast<Exp_t*>(value), out, ExpUsage::Closure); break; 1013 case "Exp"_id: transformExp(static_cast<Exp_t*>(value), out, ExpUsage::Closure); break;
1058 default: break; 1014 default: break;
@@ -1359,7 +1315,7 @@ private:
1359 } 1315 }
1360 } 1316 }
1361 1317
1362 void transformCond(const node_container& nodes, str_list& out, ExpUsage usage, bool unless = false) { 1318 void transformCond(const node_container& nodes, str_list& out, ExpUsage usage, bool unless, ExpList_t* assignList) {
1363 std::vector<ast_ptr<false, ast_node>> ns(false); 1319 std::vector<ast_ptr<false, ast_node>> ns(false);
1364 for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) { 1320 for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) {
1365 ns.push_back(*it); 1321 ns.push_back(*it);
@@ -1395,7 +1351,7 @@ private:
1395 for (auto j = ns.rbegin(); j != ns.rend(); ++j) { 1351 for (auto j = ns.rbegin(); j != ns.rend(); ++j) {
1396 newIf->nodes.push_back(*j); 1352 newIf->nodes.push_back(*j);
1397 } 1353 }
1398 transformCond(newIf->nodes.objects(), out, usage, unless); 1354 transformCond(newIf->nodes.objects(), out, usage, unless, assignList);
1399 return; 1355 return;
1400 } 1356 }
1401 str_list temp; 1357 str_list temp;
@@ -1504,7 +1460,7 @@ private:
1504 if (pair == ifCondPairs.front() && extraAssignment) { 1460 if (pair == ifCondPairs.front() && extraAssignment) {
1505 transformAssignment(extraAssignment, temp); 1461 transformAssignment(extraAssignment, temp);
1506 } 1462 }
1507 transformBody(pair.second, temp, usage != ExpUsage::Common); 1463 transformBody(pair.second, temp, usage, assignList);
1508 popScope(); 1464 popScope();
1509 } 1465 }
1510 if (!pair.first) { 1466 if (!pair.first) {
@@ -1523,12 +1479,12 @@ private:
1523 out.push_back(join(temp)); 1479 out.push_back(join(temp));
1524 } 1480 }
1525 1481
1526 void transformIf(If_t* ifNode, str_list& out, ExpUsage usage) { 1482 void transformIf(If_t* ifNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
1527 transformCond(ifNode->nodes.objects(), out, usage); 1483 transformCond(ifNode->nodes.objects(), out, usage, false, assignList);
1528 } 1484 }
1529 1485
1530 void transformUnless(Unless_t* unless, str_list& out, ExpUsage usage) { 1486 void transformUnless(Unless_t* unless, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
1531 transformCond(unless->nodes.objects(), out, usage, true); 1487 transformCond(unless->nodes.objects(), out, usage, true, assignList);
1532 } 1488 }
1533 1489
1534 void transformExpList(ExpList_t* expList, str_list& out) { 1490 void transformExpList(ExpList_t* expList, str_list& out) {
@@ -1672,13 +1628,13 @@ private:
1672 case "const_value"_id: transform_const_value(static_cast<const_value_t*>(value), out); break; 1628 case "const_value"_id: transform_const_value(static_cast<const_value_t*>(value), out); break;
1673 case "If"_id: transformIf(static_cast<If_t*>(value), out, ExpUsage::Closure); break; 1629 case "If"_id: transformIf(static_cast<If_t*>(value), out, ExpUsage::Closure); break;
1674 case "Unless"_id: transformUnless(static_cast<Unless_t*>(value), out, ExpUsage::Closure); break; 1630 case "Unless"_id: transformUnless(static_cast<Unless_t*>(value), out, ExpUsage::Closure); break;
1675 case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break; 1631 case "Switch"_id: transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Closure); break;
1676 case "With"_id: transformWithClosure(static_cast<With_t*>(value), out); break; 1632 case "With"_id: transformWithClosure(static_cast<With_t*>(value), out); break;
1677 case "ClassDecl"_id: transformClassDeclClosure(static_cast<ClassDecl_t*>(value), out); break; 1633 case "ClassDecl"_id: transformClassDeclClosure(static_cast<ClassDecl_t*>(value), out); break;
1678 case "ForEach"_id: transformForEachClosure(static_cast<ForEach_t*>(value), out); break; 1634 case "ForEach"_id: transformForEachClosure(static_cast<ForEach_t*>(value), out); break;
1679 case "For"_id: transformForClosure(static_cast<For_t*>(value), out); break; 1635 case "For"_id: transformForClosure(static_cast<For_t*>(value), out); break;
1680 case "While"_id: transformWhileClosure(static_cast<While_t*>(value), out); break; 1636 case "While"_id: transformWhileClosure(static_cast<While_t*>(value), out); break;
1681 case "Do"_id: transformDoClosure(static_cast<Do_t*>(value), out); break; 1637 case "Do"_id: transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break;
1682 case "unary_exp"_id: transform_unary_exp(static_cast<unary_exp_t*>(value), out); break; 1638 case "unary_exp"_id: transform_unary_exp(static_cast<unary_exp_t*>(value), out); break;
1683 case "TblComprehension"_id: transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Closure); break; 1639 case "TblComprehension"_id: transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Closure); break;
1684 case "TableLit"_id: transformTableLit(static_cast<TableLit_t*>(value), out); break; 1640 case "TableLit"_id: transformTableLit(static_cast<TableLit_t*>(value), out); break;
@@ -1699,7 +1655,7 @@ private:
1699 if (auto argsDef = funLit->argsDef.get()) { 1655 if (auto argsDef = funLit->argsDef.get()) {
1700 transformFnArgsDef(argsDef, temp); 1656 transformFnArgsDef(argsDef, temp);
1701 if (funLit->body) { 1657 if (funLit->body) {
1702 transformBody(funLit->body, temp, true); 1658 transformBody(funLit->body, temp, ExpUsage::Return);
1703 } else { 1659 } else {
1704 temp.push_back(Empty); 1660 temp.push_back(Empty);
1705 } 1661 }
@@ -1720,7 +1676,7 @@ private:
1720 } 1676 }
1721 } else { 1677 } else {
1722 if (funLit->body) { 1678 if (funLit->body) {
1723 transformBody(funLit->body, temp, true); 1679 transformBody(funLit->body, temp, ExpUsage::Return);
1724 } else { 1680 } else {
1725 temp.push_back(Empty); 1681 temp.push_back(Empty);
1726 } 1682 }
@@ -1740,7 +1696,19 @@ private:
1740 out.push_back(clearBuf()); 1696 out.push_back(clearBuf());
1741 } 1697 }
1742 1698
1743 void transformCodes(const node_container& nodes, str_list& out, bool implicitReturn) { 1699 void transformBody(Body_t* body, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
1700 auto x = body;
1701 if (auto stmt = body->content.as<Statement_t>()) {
1702 auto block = x->new_ptr<Block_t>();
1703 block->statements.push_back(stmt);
1704 transformBlock(block, out, usage, assignList);
1705 } else {
1706 transformBlock(body->content.to<Block_t>(), out, usage, assignList);
1707 }
1708 }
1709
1710 void transformBlock(Block_t* block, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
1711 const auto& nodes = block->statements.objects();
1744 LocalMode mode = LocalMode::None; 1712 LocalMode mode = LocalMode::None;
1745 Local_t* any = nullptr, *capital = nullptr; 1713 Local_t* any = nullptr, *capital = nullptr;
1746 for (auto it = nodes.begin(); it != nodes.end(); ++it) { 1714 for (auto it = nodes.begin(); it != nodes.end(); ++it) {
@@ -1802,7 +1770,7 @@ private:
1802 newStmt->content.set(expListAssign); 1770 newStmt->content.set(expListAssign);
1803 newBlock->statements.push_back(newStmt); 1771 newBlock->statements.push_back(newStmt);
1804 } 1772 }
1805 transformBlock(newBlock, out, implicitReturn); 1773 transformBlock(newBlock, out, usage, assignList);
1806 return; 1774 return;
1807 } 1775 }
1808 if (auto local = stmt->content.as<Local_t>()) { 1776 if (auto local = stmt->content.as<Local_t>()) {
@@ -1873,21 +1841,52 @@ private:
1873 } 1841 }
1874 } 1842 }
1875 } 1843 }
1876 if (implicitReturn) { 1844 switch (usage) {
1877 BLOCK_START 1845 case ExpUsage::Closure:
1878 BREAK_IF(nodes.empty()); 1846 case ExpUsage::Return: {
1879 auto last = static_cast<Statement_t*>(nodes.back()); 1847 BLOCK_START
1880 auto x = last; 1848 BREAK_IF(nodes.empty());
1881 auto expList = expListFrom(last); 1849 auto last = static_cast<Statement_t*>(nodes.back());
1882 BREAK_IF(!expList || 1850 auto x = last;
1883 (last->appendix && 1851 auto expList = expListFrom(last);
1884 last->appendix->item.is<CompInner_t>())); 1852 BREAK_IF(!expList ||
1885 auto expListLow = x->new_ptr<ExpListLow_t>(); 1853 (last->appendix &&
1886 expListLow->exprs.dup(expList->exprs); 1854 last->appendix->item.is<CompInner_t>()));
1887 auto returnNode = x->new_ptr<Return_t>(); 1855 auto expListLow = x->new_ptr<ExpListLow_t>();
1888 returnNode->valueList.set(expListLow); 1856 expListLow->exprs.dup(expList->exprs);
1889 last->content.set(returnNode); 1857 auto returnNode = x->new_ptr<Return_t>();
1890 BLOCK_END 1858 returnNode->valueList.set(expListLow);
1859 last->content.set(returnNode);
1860 BLOCK_END
1861 break;
1862 }
1863 case ExpUsage::Assignment: {
1864 auto last = lastStatementFrom(block);
1865 if (!last) return;
1866 bool lastAssignable = expListFrom(last) || ast_is<For_t, ForEach_t, While_t>(last->content);
1867 if (lastAssignable) {
1868 auto x = last;
1869 auto newAssignment = x->new_ptr<ExpListAssign_t>();
1870 newAssignment->expList.set(assignList);
1871 auto assign = x->new_ptr<Assign_t>();
1872 if (auto valueList = last->content.as<ExpListAssign_t>()) {
1873 assign->values.dup(valueList->expList->exprs);
1874 } else {
1875 auto simpleValue = x->new_ptr<SimpleValue_t>();
1876 simpleValue->value.set(last->content);
1877 auto value = x->new_ptr<Value_t>();
1878 value->item.set(simpleValue);
1879 auto exp = x->new_ptr<Exp_t>();
1880 exp->value.set(value);
1881 assign->values.push_back(exp);
1882 }
1883 newAssignment->action.set(assign);
1884 last->content.set(newAssignment);
1885 }
1886 break;
1887 }
1888 default:
1889 break;
1891 } 1890 }
1892 if (!nodes.empty()) { 1891 if (!nodes.empty()) {
1893 str_list temp; 1892 str_list temp;
@@ -1900,18 +1899,6 @@ private:
1900 } 1899 }
1901 } 1900 }
1902 1901
1903 void transformBody(Body_t* body, str_list& out, bool implicitReturn = false) {
1904 if (auto stmt = body->content.as<Statement_t>()) {
1905 transformCodes(node_container{stmt}, out, implicitReturn);
1906 } else {
1907 transformCodes(body->content.to<Block_t>()->statements.objects(), out, implicitReturn);
1908 }
1909 }
1910
1911 void transformBlock(Block_t* block, str_list& out, bool implicitReturn = true) {
1912 transformCodes(block->statements.objects(), out, implicitReturn);
1913 }
1914
1915 void transformReturn(Return_t* returnNode, str_list& out) { 1902 void transformReturn(Return_t* returnNode, str_list& out) {
1916 if (auto valueList = returnNode->valueList.get()) { 1903 if (auto valueList = returnNode->valueList.get()) {
1917 if (valueList->exprs.size() == 1) { 1904 if (valueList->exprs.size() == 1) {
@@ -1938,10 +1925,10 @@ private:
1938 transformClassDecl(static_cast<ClassDecl_t*>(value), out, ExpUsage::Return); 1925 transformClassDecl(static_cast<ClassDecl_t*>(value), out, ExpUsage::Return);
1939 return; 1926 return;
1940 case "Do"_id: 1927 case "Do"_id:
1941 transformDo(static_cast<Do_t*>(value), out, true); 1928 transformDo(static_cast<Do_t*>(value), out, ExpUsage::Return);
1942 return; 1929 return;
1943 case "Switch"_id: 1930 case "Switch"_id:
1944 transformSwitch(static_cast<Switch_t*>(value), out, true); 1931 transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Return);
1945 return; 1932 return;
1946 case "While"_id: 1933 case "While"_id:
1947 transformWhileInPlace(static_cast<While_t*>(value), out); 1934 transformWhileInPlace(static_cast<While_t*>(value), out);
@@ -2541,16 +2528,11 @@ private:
2541 } 2528 }
2542 switch (usage) { 2529 switch (usage) {
2543 case ExpUsage::Common: 2530 case ExpUsage::Common:
2544 transformBlock(block, out, false);
2545 return;
2546 case ExpUsage::Return: 2531 case ExpUsage::Return:
2547 transformBlock(block, out, true); 2532 transformBlock(block, out, usage);
2548 return; 2533 return;
2549 case ExpUsage::Assignment: { 2534 case ExpUsage::Assignment: {
2550 auto body = x->new_ptr<Body_t>(); 2535 transformBlock(block, out, ExpUsage::Assignment, assignList);
2551 body->content.set(block);
2552 assignLastExplist(assignList, body);
2553 transformBlock(block, out);
2554 return; 2536 return;
2555 } 2537 }
2556 default: 2538 default:
@@ -2996,7 +2978,7 @@ private:
2996 out.push_back(clearBuf()); 2978 out.push_back(clearBuf());
2997 } 2979 }
2998 2980
2999 void transformLoopBody(Body_t* body, str_list& out, const std::string& appendContent) { 2981 void transformLoopBody(Body_t* body, str_list& out, const std::string& appendContent, ExpUsage usage, ExpList_t* assignList = nullptr) {
3000 str_list temp; 2982 str_list temp;
3001 bool withContinue = traversal::Stop == body->traverse([&](ast_node* node) { 2983 bool withContinue = traversal::Stop == body->traverse([&](ast_node* node) {
3002 switch (node->getId()) { 2984 switch (node->getId()) {
@@ -3020,7 +3002,7 @@ private:
3020 _continueVars.push(continueVar); 3002 _continueVars.push(continueVar);
3021 pushScope(); 3003 pushScope();
3022 } 3004 }
3023 transformBody(body, temp); 3005 transformBody(body, temp, usage, assignList);
3024 if (withContinue) { 3006 if (withContinue) {
3025 if (!appendContent.empty()) { 3007 if (!appendContent.empty()) {
3026 _buf << indent() << appendContent; 3008 _buf << indent() << appendContent;
@@ -3042,7 +3024,7 @@ private:
3042 void transformFor(For_t* forNode, str_list& out) { 3024 void transformFor(For_t* forNode, str_list& out) {
3043 str_list temp; 3025 str_list temp;
3044 transformForHead(forNode, temp); 3026 transformForHead(forNode, temp);
3045 transformLoopBody(forNode->body, temp, Empty); 3027 transformLoopBody(forNode->body, temp, Empty, ExpUsage::Common);
3046 popScope(); 3028 popScope();
3047 out.push_back(join(temp) + indent() + s("end"sv) + nlr(forNode)); 3029 out.push_back(join(temp) + indent() + s("end"sv) + nlr(forNode));
3048 } 3030 }
@@ -3058,9 +3040,8 @@ private:
3058 out.push_back(clearBuf()); 3040 out.push_back(clearBuf());
3059 transformForHead(forNode, out); 3041 transformForHead(forNode, out);
3060 auto expList = toAst<ExpList_t>(accum + s("["sv) + len + s("]"sv), x); 3042 auto expList = toAst<ExpList_t>(accum + s("["sv) + len + s("]"sv), x);
3061 assignLastExplist(expList, forNode->body);
3062 auto lenLine = len + s(" = "sv) + len + s(" + 1"sv) + nlr(forNode->body); 3043 auto lenLine = len + s(" = "sv) + len + s(" + 1"sv) + nlr(forNode->body);
3063 transformLoopBody(forNode->body, out, lenLine); 3044 transformLoopBody(forNode->body, out, lenLine, ExpUsage::Assignment, expList);
3064 popScope(); 3045 popScope();
3065 out.push_back(indent() + s("end"sv) + nlr(forNode)); 3046 out.push_back(indent() + s("end"sv) + nlr(forNode));
3066 return accum; 3047 return accum;
@@ -3110,7 +3091,7 @@ private:
3110 void transformForEach(ForEach_t* forEach, str_list& out) { 3091 void transformForEach(ForEach_t* forEach, str_list& out) {
3111 str_list temp; 3092 str_list temp;
3112 transformForEachHead(forEach->nameList, forEach->loopValue, temp); 3093 transformForEachHead(forEach->nameList, forEach->loopValue, temp);
3113 transformLoopBody(forEach->body, temp, Empty); 3094 transformLoopBody(forEach->body, temp, Empty, ExpUsage::Common);
3114 popScope(); 3095 popScope();
3115 out.push_back(temp.front() + temp.back() + indent() + s("end"sv) + nlr(forEach)); 3096 out.push_back(temp.front() + temp.back() + indent() + s("end"sv) + nlr(forEach));
3116 } 3097 }
@@ -3126,9 +3107,8 @@ private:
3126 out.push_back(clearBuf()); 3107 out.push_back(clearBuf());
3127 transformForEachHead(forEach->nameList, forEach->loopValue, out); 3108 transformForEachHead(forEach->nameList, forEach->loopValue, out);
3128 auto expList = toAst<ExpList_t>(accum + s("["sv) + len + s("]"sv), x); 3109 auto expList = toAst<ExpList_t>(accum + s("["sv) + len + s("]"sv), x);
3129 assignLastExplist(expList, forEach->body);
3130 auto lenLine = len + s(" = "sv) + len + s(" + 1"sv) + nlr(forEach->body); 3110 auto lenLine = len + s(" = "sv) + len + s(" + 1"sv) + nlr(forEach->body);
3131 transformLoopBody(forEach->body, out, lenLine); 3111 transformLoopBody(forEach->body, out, lenLine, ExpUsage::Assignment, expList);
3132 popScope(); 3112 popScope();
3133 out.push_back(indent() + s("end"sv) + nlr(forEach)); 3113 out.push_back(indent() + s("end"sv) + nlr(forEach));
3134 return accum; 3114 return accum;
@@ -3763,7 +3743,7 @@ private:
3763 } 3743 }
3764 } 3744 }
3765 _withVars.push(withVar); 3745 _withVars.push(withVar);
3766 transformBody(with->body, temp); 3746 transformBody(with->body, temp, ExpUsage::Common);
3767 _withVars.pop(); 3747 _withVars.pop();
3768 if (assignList) { 3748 if (assignList) {
3769 auto assignment = x->new_ptr<ExpListAssign_t>(); 3749 auto assignment = x->new_ptr<ExpListAssign_t>();
@@ -3975,23 +3955,21 @@ private:
3975 transformTable(table, table->values.objects(), out); 3955 transformTable(table, table->values.objects(), out);
3976 } 3956 }
3977 3957
3978 void transformDo(Do_t* doNode, str_list& out, bool implicitReturn = false) { 3958 void transformDo(Do_t* doNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
3979 str_list temp;
3980 temp.push_back(indent() + s("do"sv) + nll(doNode));
3981 pushScope();
3982 transformBody(doNode->body, temp, implicitReturn);
3983 popScope();
3984 temp.push_back(indent() + s("end"sv) + nlr(doNode));
3985 out.push_back(join(temp));
3986 }
3987
3988 void transformDoClosure(Do_t* doNode, str_list& out) {
3989 str_list temp; 3959 str_list temp;
3990 temp.push_back(s("(function()"sv) + nll(doNode)); 3960 if (usage == ExpUsage::Closure) {
3961 temp.push_back(s("(function()"sv) + nll(doNode));
3962 } else {
3963 temp.push_back(indent() + s("do"sv) + nll(doNode));
3964 }
3991 pushScope(); 3965 pushScope();
3992 transformBody(doNode->body, temp, true); 3966 transformBody(doNode->body, temp, usage, assignList);
3993 popScope(); 3967 popScope();
3994 temp.push_back(indent() + s("end)()"sv)); 3968 if (usage == ExpUsage::Closure) {
3969 temp.push_back(indent() + s("end)()"sv));
3970 } else {
3971 temp.push_back(indent() + s("end"sv) + nlr(doNode));
3972 }
3995 out.push_back(join(temp)); 3973 out.push_back(join(temp));
3996 } 3974 }
3997 3975
@@ -4154,9 +4132,8 @@ private:
4154 temp.back() = indent() + s("while "sv) + temp.back() + s(" do"sv) + nll(whileNode); 4132 temp.back() = indent() + s("while "sv) + temp.back() + s(" do"sv) + nll(whileNode);
4155 pushScope(); 4133 pushScope();
4156 auto assignLeft = toAst<ExpList_t>(accumVar + s("["sv) + lenVar + s("]"sv), x); 4134 auto assignLeft = toAst<ExpList_t>(accumVar + s("["sv) + lenVar + s("]"sv), x);
4157 assignLastExplist(assignLeft, whileNode->body);
4158 auto lenLine = lenVar + s(" = "sv) + lenVar + s(" + 1"sv) + nlr(whileNode); 4135 auto lenLine = lenVar + s(" = "sv) + lenVar + s(" + 1"sv) + nlr(whileNode);
4159 transformLoopBody(whileNode->body, temp, lenLine); 4136 transformLoopBody(whileNode->body, temp, lenLine, ExpUsage::Assignment, assignLeft);
4160 popScope(); 4137 popScope();
4161 temp.push_back(indent() + s("end"sv) + nlr(whileNode)); 4138 temp.push_back(indent() + s("end"sv) + nlr(whileNode));
4162 if (expList) { 4139 if (expList) {
@@ -4191,9 +4168,8 @@ private:
4191 temp.back() = indent() + s("while "sv) + temp.back() + s(" do"sv) + nll(whileNode); 4168 temp.back() = indent() + s("while "sv) + temp.back() + s(" do"sv) + nll(whileNode);
4192 pushScope(); 4169 pushScope();
4193 auto assignLeft = toAst<ExpList_t>(accumVar + s("["sv) + lenVar + s("]"sv), x); 4170 auto assignLeft = toAst<ExpList_t>(accumVar + s("["sv) + lenVar + s("]"sv), x);
4194 assignLastExplist(assignLeft, whileNode->body);
4195 auto lenLine = lenVar + s(" = "sv) + lenVar + s(" + 1"sv) + nlr(whileNode); 4171 auto lenLine = lenVar + s(" = "sv) + lenVar + s(" + 1"sv) + nlr(whileNode);
4196 transformLoopBody(whileNode->body, temp, lenLine); 4172 transformLoopBody(whileNode->body, temp, lenLine, ExpUsage::Assignment, assignLeft);
4197 popScope(); 4173 popScope();
4198 temp.push_back(indent() + s("end"sv) + nlr(whileNode)); 4174 temp.push_back(indent() + s("end"sv) + nlr(whileNode));
4199 temp.push_back(indent() + s("return "sv) + accumVar + nlr(whileNode)); 4175 temp.push_back(indent() + s("return "sv) + accumVar + nlr(whileNode));
@@ -4206,7 +4182,7 @@ private:
4206 str_list temp; 4182 str_list temp;
4207 pushScope(); 4183 pushScope();
4208 transformExp(whileNode->condition, temp, ExpUsage::Closure); 4184 transformExp(whileNode->condition, temp, ExpUsage::Closure);
4209 transformLoopBody(whileNode->body, temp, Empty); 4185 transformLoopBody(whileNode->body, temp, Empty, ExpUsage::Common);
4210 popScope(); 4186 popScope();
4211 _buf << indent() << "while "sv << temp.front() << " do"sv << nll(whileNode); 4187 _buf << indent() << "while "sv << temp.front() << " do"sv << nll(whileNode);
4212 _buf << temp.back(); 4188 _buf << temp.back();
@@ -4214,18 +4190,12 @@ private:
4214 out.push_back(clearBuf()); 4190 out.push_back(clearBuf());
4215 } 4191 }
4216 4192
4217 void transformSwitchClosure(Switch_t* switchNode, str_list& out) { 4193 void transformSwitch(Switch_t* switchNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
4218 str_list temp;
4219 temp.push_back(s("(function()"sv) + nll(switchNode));
4220 pushScope();
4221 transformSwitch(switchNode, temp, true);
4222 popScope();
4223 temp.push_back(indent() + s("end)()"sv));
4224 out.push_back(join(temp));
4225 }
4226
4227 void transformSwitch(Switch_t* switchNode, str_list& out, bool implicitReturn = false) {
4228 str_list temp; 4194 str_list temp;
4195 if (usage == ExpUsage::Closure) {
4196 temp.push_back(s("(function()"sv) + nll(switchNode));
4197 pushScope();
4198 }
4229 auto objVar = singleVariableFrom(switchNode->target); 4199 auto objVar = singleVariableFrom(switchNode->target);
4230 if (objVar.empty()) { 4200 if (objVar.empty()) {
4231 objVar = getUnusedName("_exp_"sv); 4201 objVar = getUnusedName("_exp_"sv);
@@ -4251,16 +4221,20 @@ private:
4251 } 4221 }
4252 temp.back().append(s(" then"sv) + nll(branch)); 4222 temp.back().append(s(" then"sv) + nll(branch));
4253 pushScope(); 4223 pushScope();
4254 transformBody(branch->body, temp, implicitReturn); 4224 transformBody(branch->body, temp, usage, assignList);
4255 popScope(); 4225 popScope();
4256 } 4226 }
4257 if (switchNode->lastBranch) { 4227 if (switchNode->lastBranch) {
4258 temp.push_back(indent() + s("else"sv) + nll(switchNode->lastBranch)); 4228 temp.push_back(indent() + s("else"sv) + nll(switchNode->lastBranch));
4259 pushScope(); 4229 pushScope();
4260 transformBody(switchNode->lastBranch, temp, implicitReturn); 4230 transformBody(switchNode->lastBranch, temp, usage, assignList);
4261 popScope(); 4231 popScope();
4262 } 4232 }
4263 temp.push_back(indent() + s("end"sv) + nlr(switchNode)); 4233 temp.push_back(indent() + s("end"sv) + nlr(switchNode));
4234 if (usage == ExpUsage::Closure) {
4235 popScope();
4236 temp.push_back(indent() + s("end)()"sv));
4237 }
4264 out.push_back(join(temp)); 4238 out.push_back(join(temp));
4265 } 4239 }
4266 4240
diff --git a/src/MoonP/moon_parser.h b/src/MoonP/moon_parser.h
index 2107a14..2b6e2ae 100644
--- a/src/MoonP/moon_parser.h
+++ b/src/MoonP/moon_parser.h
@@ -79,7 +79,6 @@ protected:
79 std::stack<bool> doStack; 79 std::stack<bool> doStack;
80 }; 80 };
81 81
82
83 template <class T> 82 template <class T>
84 inline rule& getRule() { 83 inline rule& getRule() {
85 return getRule(identity<T>()); 84 return getRule(identity<T>());