diff options
author | Li Jin <dragon-fly@qq.com> | 2020-02-03 15:44:20 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2020-02-03 15:44:20 +0800 |
commit | d75848152e337fc9d3a4041ec310fea07476c0a8 (patch) | |
tree | 22e74a062b8eaff1fd99f002c473ccdfd5181157 | |
parent | d8901102a1e39e651b08b66257c176b5803b9bc0 (diff) | |
download | yuescript-d75848152e337fc9d3a4041ec310fea07476c0a8.tar.gz yuescript-d75848152e337fc9d3a4041ec310fea07476c0a8.tar.bz2 yuescript-d75848152e337fc9d3a4041ec310fea07476c0a8.zip |
fix some cases when using backcall with assignment.
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | makefile | 4 | ||||
-rw-r--r-- | spec/inputs/assign.moon | 4 | ||||
-rw-r--r-- | spec/inputs/backcall.moon | 10 | ||||
-rw-r--r-- | src/MoonP/moon_compiler.cpp | 260 | ||||
-rw-r--r-- | src/MoonP/moon_parser.h | 1 |
7 files changed, 137 insertions, 149 deletions
@@ -1,3 +1,3 @@ | |||
1 | moonc | 1 | moonp |
2 | build | 2 | build |
3 | spec/outputs | 3 | spec/outputs |
@@ -182,10 +182,11 @@ end | |||
182 | ## Standalone Compiler Usage | 182 | ## Standalone Compiler Usage |
183 | 183 | ||
184 | Test compiler with `make test`. | 184 | Test compiler with `make test`. |
185 | Run `moonc` complier in project folder with: | 185 | Run `moonp` complier in project folder with: |
186 | |||
186 | ```shell | 187 | ```shell |
187 | make | 188 | make |
188 | ./moonc -h | 189 | ./moonp -h |
189 | ``` | 190 | ``` |
190 | 191 | ||
191 | ## License | 192 | ## License |
@@ -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 |
3 | BIN_NAME := moonc | 3 | BIN_NAME := moonp |
4 | # Compiler used | 4 | # Compiler used |
5 | CXX ?= g++ | 5 | CXX ?= 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 |
207 | test: release | 207 | test: 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 |
212 | all: $(BIN_PATH)/$(BIN_NAME) | 212 | all: $(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 | ||
29 | c, d = 1, 2 if true | 29 | c, d = 1, 2 if true |
30 | |||
31 | x = (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 | ||
61 | do | ||
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 | |||
61 | alert "hi" | 71 | alert "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>()); |