diff options
| -rw-r--r-- | MoonParser/moon_ast.cpp | 524 | ||||
| -rw-r--r-- | MoonParser/moon_ast.h | 8 | ||||
| -rw-r--r-- | MoonParser/moon_parser.cpp | 5 |
3 files changed, 461 insertions, 76 deletions
diff --git a/MoonParser/moon_ast.cpp b/MoonParser/moon_ast.cpp index 52fbd68..50c13db 100644 --- a/MoonParser/moon_ast.cpp +++ b/MoonParser/moon_ast.cpp | |||
| @@ -420,18 +420,6 @@ private: | |||
| 420 | return firstValue; | 420 | return firstValue; |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | void noop(ast_node* node, str_list& out) { | ||
| 424 | auto str = _converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); | ||
| 425 | out.push_back(s("<"sv) + node->getName() + s(">"sv) + trim(str)); | ||
| 426 | // out.push_back(trim(str)); | ||
| 427 | } | ||
| 428 | |||
| 429 | void noopnl(ast_node* node, str_list& out) { | ||
| 430 | auto str = _converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); | ||
| 431 | out.push_back(s("<"sv) + node->getName() + s(">"sv) + trim(str) + nll(node)); | ||
| 432 | // out.push_back(trim(str) + nll(node)); | ||
| 433 | } | ||
| 434 | |||
| 435 | Statement_t* lastStatementFrom(Body_t* body) { | 423 | Statement_t* lastStatementFrom(Body_t* body) { |
| 436 | if (auto stmt = body->content.as<Statement_t>()) { | 424 | if (auto stmt = body->content.as<Statement_t>()) { |
| 437 | return stmt; | 425 | return stmt; |
| @@ -561,7 +549,15 @@ private: | |||
| 561 | auto stmt = new_ptr<Statement_t>(); | 549 | auto stmt = new_ptr<Statement_t>(); |
| 562 | stmt->content.set(statement->content); | 550 | stmt->content.set(statement->content); |
| 563 | comp->value.set(stmt); | 551 | comp->value.set(stmt); |
| 564 | statement->content.set(comp); | 552 | auto simpleValue = new_ptr<SimpleValue_t>(); |
| 553 | simpleValue->value.set(comp); | ||
| 554 | auto value = new_ptr<Value_t>(); | ||
| 555 | value->item.set(simpleValue); | ||
| 556 | auto exp = new_ptr<Exp_t>(); | ||
| 557 | exp->value.set(value); | ||
| 558 | auto expList = new_ptr<ExpList_t>(); | ||
| 559 | expList->exprs.push_back(exp); | ||
| 560 | statement->content.set(expList); | ||
| 565 | statement->appendix.set(nullptr); | 561 | statement->appendix.set(nullptr); |
| 566 | break; | 562 | break; |
| 567 | } | 563 | } |
| @@ -576,16 +572,13 @@ private: | |||
| 576 | switch (content->getId()) { | 572 | switch (content->getId()) { |
| 577 | case "Import"_id: transformImport(static_cast<Import_t*>(content), out); break; | 573 | case "Import"_id: transformImport(static_cast<Import_t*>(content), out); break; |
| 578 | case "While"_id: transformWhile(static_cast<While_t*>(content), out); break; | 574 | case "While"_id: transformWhile(static_cast<While_t*>(content), out); break; |
| 579 | case "With"_id: transformWith(static_cast<With_t*>(content), out); break; | ||
| 580 | case "For"_id: transformFor(static_cast<For_t*>(content), out); break; | 575 | case "For"_id: transformFor(static_cast<For_t*>(content), out); break; |
| 581 | case "ForEach"_id: transformForEach(static_cast<ForEach_t*>(content), out); break; | 576 | case "ForEach"_id: transformForEach(static_cast<ForEach_t*>(content), out); break; |
| 582 | case "Switch"_id: transformSwitch(static_cast<Switch_t*>(content), out); break; | ||
| 583 | case "Return"_id: transformReturn(static_cast<Return_t*>(content), out); break; | 577 | case "Return"_id: transformReturn(static_cast<Return_t*>(content), out); break; |
| 584 | case "Local"_id: transformLocal(static_cast<Local_t*>(content), out); break; | 578 | case "Local"_id: transformLocal(static_cast<Local_t*>(content), out); break; |
| 585 | case "Export"_id: transformExport(static_cast<Export_t*>(content), out); break; | 579 | case "Export"_id: transformExport(static_cast<Export_t*>(content), out); break; |
| 586 | case "BreakLoop"_id: transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; | 580 | case "BreakLoop"_id: transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; |
| 587 | case "Assignment"_id: transformAssignment(static_cast<Assignment_t*>(content), out); break; | 581 | case "Assignment"_id: transformAssignment(static_cast<Assignment_t*>(content), out); break; |
| 588 | case "Comprehension"_id: transformCompCommon(static_cast<Comprehension_t*>(content), out); break; | ||
| 589 | case "ExpList"_id: { | 582 | case "ExpList"_id: { |
| 590 | auto expList = static_cast<ExpList_t*>(content); | 583 | auto expList = static_cast<ExpList_t*>(content); |
| 591 | if (expList->exprs.objects().empty()) { | 584 | if (expList->exprs.objects().empty()) { |
| @@ -606,6 +599,7 @@ private: | |||
| 606 | case "For"_id: transformFor(static_cast<For_t*>(value), out); break; | 599 | case "For"_id: transformFor(static_cast<For_t*>(value), out); break; |
| 607 | case "While"_id: transformWhile(static_cast<While_t*>(value), out); break; | 600 | case "While"_id: transformWhile(static_cast<While_t*>(value), out); break; |
| 608 | case "Do"_id: transformDo(static_cast<Do_t*>(value), out); break; | 601 | case "Do"_id: transformDo(static_cast<Do_t*>(value), out); break; |
| 602 | case "Comprehension"_id: transformCompCommon(static_cast<Comprehension_t*>(value), out); break; | ||
| 609 | default: specialSingleValue = false; break; | 603 | default: specialSingleValue = false; break; |
| 610 | } | 604 | } |
| 611 | if (specialSingleValue) { | 605 | if (specialSingleValue) { |
| @@ -653,25 +647,24 @@ private: | |||
| 653 | 647 | ||
| 654 | str_list transformAssignDefs(ExpList_t* expList) { | 648 | str_list transformAssignDefs(ExpList_t* expList) { |
| 655 | str_list preDefs; | 649 | str_list preDefs; |
| 656 | expList->traverse([&](ast_node* child) { | 650 | for (auto exp_ : expList->exprs.objects()) { |
| 657 | if (child->getId() == "Value"_id) { | 651 | auto exp = static_cast<Exp_t*>(exp_); |
| 658 | if (auto callable = child->getByPath<ChainValue_t, Callable_t>()) { | 652 | if (auto value = singleValueFrom(exp)) { |
| 659 | if (ast_is<Variable_t>(callable->item)) { | 653 | if (auto chain = value->item.as<ChainValue_t>()) { |
| 654 | do { | ||
| 655 | if (chain->items.size() != 1) break; | ||
| 656 | auto callable = ast_cast<Callable_t>(chain->items.front()); | ||
| 657 | if (!callable) break; | ||
| 660 | auto name = toString(callable->item); | 658 | auto name = toString(callable->item); |
| 661 | if (addToScope(name)) { | 659 | if (addToScope(name)) { |
| 662 | preDefs.push_back(name); | 660 | preDefs.push_back(name); |
| 663 | } | 661 | } |
| 664 | } else if (callable->getByPath<SelfName_t, self_t>()) { | 662 | } while (false); |
| 665 | auto self = s("self"sv); | ||
| 666 | if (addToScope(self)) { | ||
| 667 | preDefs.push_back(self); | ||
| 668 | } | ||
| 669 | } | ||
| 670 | } | 663 | } |
| 671 | return traversal::Return; | 664 | } else { |
| 665 | throw std::logic_error("left hand expression is not assignable"); | ||
| 672 | } | 666 | } |
| 673 | return traversal::Continue; | 667 | } |
| 674 | }); | ||
| 675 | return preDefs; | 668 | return preDefs; |
| 676 | } | 669 | } |
| 677 | 670 | ||
| @@ -706,12 +699,22 @@ private: | |||
| 706 | 699 | ||
| 707 | void assignLastExplist(ExpList_t* expList, Body_t* body) { | 700 | void assignLastExplist(ExpList_t* expList, Body_t* body) { |
| 708 | auto last = lastStatementFrom(body); | 701 | auto last = lastStatementFrom(body); |
| 709 | auto valueList = last ? last->content.as<ExpList_t>() : nullptr; | 702 | bool lastAssignable = last && ast_is<ExpList_t, For_t, ForEach_t, While_t>(last->content); |
| 710 | if (last && valueList) { | 703 | if (lastAssignable) { |
| 711 | auto newAssignment = new_ptr<Assignment_t>(); | 704 | auto newAssignment = new_ptr<Assignment_t>(); |
| 712 | newAssignment->assignable.set(expList); | 705 | newAssignment->assignable.set(expList); |
| 713 | auto assign = new_ptr<Assign_t>(); | 706 | auto assign = new_ptr<Assign_t>(); |
| 714 | assign->values.dup(valueList->exprs); | 707 | if (auto valueList = last->content.as<ExpList_t>()) { |
| 708 | assign->values.dup(valueList->exprs); | ||
| 709 | } else { | ||
| 710 | auto simpleValue = new_ptr<SimpleValue_t>(); | ||
| 711 | simpleValue->value.set(last->content); | ||
| 712 | auto value = new_ptr<Value_t>(); | ||
| 713 | value->item.set(simpleValue); | ||
| 714 | auto exp = new_ptr<Exp_t>(); | ||
| 715 | exp->value.set(value); | ||
| 716 | assign->values.push_back(exp); | ||
| 717 | } | ||
| 715 | newAssignment->target.set(assign); | 718 | newAssignment->target.set(assign); |
| 716 | last->content.set(newAssignment); | 719 | last->content.set(newAssignment); |
| 717 | } | 720 | } |
| @@ -767,19 +770,19 @@ private: | |||
| 767 | out.back() = preDefine + out.back(); | 770 | out.back() = preDefine + out.back(); |
| 768 | return; | 771 | return; |
| 769 | } | 772 | } |
| 773 | if (auto withNode = ast_cast<With_t>(value)) { | ||
| 774 | str_list temp; | ||
| 775 | auto expList = assignment->assignable.get(); | ||
| 776 | std::string preDefine = getPredefine(assignment); | ||
| 777 | transformWith(withNode, temp, expList); | ||
| 778 | out.push_back(preDefine + temp.back()); | ||
| 779 | return; | ||
| 780 | } | ||
| 770 | auto exp = ast_cast<Exp_t>(value); | 781 | auto exp = ast_cast<Exp_t>(value); |
| 771 | if (!exp) break; | 782 | if (!exp) break; |
| 772 | if (auto simpleVal = exp->value->item.as<SimpleValue_t>()) { | 783 | if (auto simpleVal = exp->value->item.as<SimpleValue_t>()) { |
| 773 | auto valueItem = simpleVal->value.get(); | 784 | auto valueItem = simpleVal->value.get(); |
| 774 | switch (valueItem->getId()) { | 785 | switch (valueItem->getId()) { |
| 775 | case "With"_id: { | ||
| 776 | str_list temp; | ||
| 777 | auto expList = assignment->assignable.get(); | ||
| 778 | std::string preDefine = getPredefine(assignment); | ||
| 779 | transformWith(static_cast<With_t*>(valueItem), temp, expList); | ||
| 780 | out.push_back(preDefine + temp.front()); | ||
| 781 | return; | ||
| 782 | } | ||
| 783 | case "Do"_id: { | 786 | case "Do"_id: { |
| 784 | auto doNode = static_cast<Do_t*>(valueItem); | 787 | auto doNode = static_cast<Do_t*>(valueItem); |
| 785 | auto expList = assignment->assignable.get(); | 788 | auto expList = assignment->assignable.get(); |
| @@ -808,7 +811,7 @@ private: | |||
| 808 | auto expList = assignment->assignable.get(); | 811 | auto expList = assignment->assignable.get(); |
| 809 | std::string preDefine = getPredefine(assignment); | 812 | std::string preDefine = getPredefine(assignment); |
| 810 | transformForInPlace(static_cast<For_t*>(valueItem), temp, expList); | 813 | transformForInPlace(static_cast<For_t*>(valueItem), temp, expList); |
| 811 | out.push_back(preDefine + temp.front()); | 814 | out.push_back(preDefine + temp.back()); |
| 812 | return; | 815 | return; |
| 813 | } | 816 | } |
| 814 | case "ForEach"_id: { | 817 | case "ForEach"_id: { |
| @@ -816,7 +819,7 @@ private: | |||
| 816 | auto expList = assignment->assignable.get(); | 819 | auto expList = assignment->assignable.get(); |
| 817 | std::string preDefine = getPredefine(assignment); | 820 | std::string preDefine = getPredefine(assignment); |
| 818 | transformForEachInPlace(static_cast<ForEach_t*>(valueItem), temp, expList); | 821 | transformForEachInPlace(static_cast<ForEach_t*>(valueItem), temp, expList); |
| 819 | out.push_back(preDefine + temp.front()); | 822 | out.push_back(preDefine + temp.back()); |
| 820 | return; | 823 | return; |
| 821 | } | 824 | } |
| 822 | case "ClassDecl"_id: { | 825 | case "ClassDecl"_id: { |
| @@ -824,7 +827,7 @@ private: | |||
| 824 | auto expList = assignment->assignable.get(); | 827 | auto expList = assignment->assignable.get(); |
| 825 | std::string preDefine = getPredefine(assignment); | 828 | std::string preDefine = getPredefine(assignment); |
| 826 | transformClassDecl(static_cast<ClassDecl_t*>(valueItem), temp, ExpUsage::Assignment, expList); | 829 | transformClassDecl(static_cast<ClassDecl_t*>(valueItem), temp, ExpUsage::Assignment, expList); |
| 827 | out.push_back(preDefine + temp.front()); | 830 | out.push_back(preDefine + temp.back()); |
| 828 | return; | 831 | return; |
| 829 | } | 832 | } |
| 830 | case "While"_id: { | 833 | case "While"_id: { |
| @@ -832,7 +835,7 @@ private: | |||
| 832 | auto expList = assignment->assignable.get(); | 835 | auto expList = assignment->assignable.get(); |
| 833 | std::string preDefine = getPredefine(assignment); | 836 | std::string preDefine = getPredefine(assignment); |
| 834 | transformWhileClosure(static_cast<While_t*>(valueItem), temp, expList); | 837 | transformWhileClosure(static_cast<While_t*>(valueItem), temp, expList); |
| 835 | out.push_back(preDefine + temp.front()); | 838 | out.push_back(preDefine + temp.back()); |
| 836 | return; | 839 | return; |
| 837 | } | 840 | } |
| 838 | } | 841 | } |
| @@ -912,7 +915,7 @@ private: | |||
| 912 | 915 | ||
| 913 | void transformAssignItem(ast_node* value, str_list& out) { | 916 | void transformAssignItem(ast_node* value, str_list& out) { |
| 914 | switch (value->getId()) { | 917 | switch (value->getId()) { |
| 915 | case "With"_id: transformWith(static_cast<With_t*>(value), out); break; | 918 | case "With"_id: transformWithClosure(static_cast<With_t*>(value), out); break; |
| 916 | case "If"_id: transformIf(static_cast<If_t*>(value), out, IfUsage::Closure); break; | 919 | case "If"_id: transformIf(static_cast<If_t*>(value), out, IfUsage::Closure); break; |
| 917 | case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break; | 920 | case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break; |
| 918 | case "TableBlock"_id: transformTableBlock(static_cast<TableBlock_t*>(value), out); break; | 921 | case "TableBlock"_id: transformTableBlock(static_cast<TableBlock_t*>(value), out); break; |
| @@ -1248,9 +1251,19 @@ private: | |||
| 1248 | if (pair.first) { | 1251 | if (pair.first) { |
| 1249 | str_list tmp; | 1252 | str_list tmp; |
| 1250 | auto condition = pair.first->condition.get(); | 1253 | auto condition = pair.first->condition.get(); |
| 1251 | transformExp(condition, tmp); | 1254 | if (unless) { |
| 1255 | if (auto value = singleValueFrom(condition)) { | ||
| 1256 | transformValue(value, tmp); | ||
| 1257 | } else { | ||
| 1258 | transformExp(condition, tmp); | ||
| 1259 | tmp.back() = s("("sv) + tmp.back() + s(")"sv); | ||
| 1260 | } | ||
| 1261 | tmp.back().insert(0, s("not "sv)); | ||
| 1262 | } else { | ||
| 1263 | transformExp(condition, tmp); | ||
| 1264 | } | ||
| 1252 | _buf << indent() << (pair == ifCondPairs.front() ? ""sv : "else"sv) << | 1265 | _buf << indent() << (pair == ifCondPairs.front() ? ""sv : "else"sv) << |
| 1253 | "if "sv << (unless ? "not ("sv : ""sv) << tmp.front() << (unless ? ") then"sv : " then"sv) << nll(condition); | 1266 | "if "sv << tmp.back() << " then"sv << nll(condition); |
| 1254 | temp.push_back(clearBuf()); | 1267 | temp.push_back(clearBuf()); |
| 1255 | } | 1268 | } |
| 1256 | if (pair.second) { | 1269 | if (pair.second) { |
| @@ -1355,7 +1368,7 @@ private: | |||
| 1355 | case "If"_id: transformIf(static_cast<If_t*>(value), out, IfUsage::Closure); break; | 1368 | case "If"_id: transformIf(static_cast<If_t*>(value), out, IfUsage::Closure); break; |
| 1356 | case "Unless"_id: transformUnless(static_cast<Unless_t*>(value), out, IfUsage::Closure); break; | 1369 | case "Unless"_id: transformUnless(static_cast<Unless_t*>(value), out, IfUsage::Closure); break; |
| 1357 | case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break; | 1370 | case "Switch"_id: transformSwitchClosure(static_cast<Switch_t*>(value), out); break; |
| 1358 | case "With"_id: transformWith(static_cast<With_t*>(value), out); break; | 1371 | case "With"_id: transformWithClosure(static_cast<With_t*>(value), out); break; |
| 1359 | case "ClassDecl"_id: transformClassDeclClosure(static_cast<ClassDecl_t*>(value), out); break; | 1372 | case "ClassDecl"_id: transformClassDeclClosure(static_cast<ClassDecl_t*>(value), out); break; |
| 1360 | case "ForEach"_id: transformForEachClosure(static_cast<ForEach_t*>(value), out); break; | 1373 | case "ForEach"_id: transformForEachClosure(static_cast<ForEach_t*>(value), out); break; |
| 1361 | case "For"_id: transformForClosure(static_cast<For_t*>(value), out); break; | 1374 | case "For"_id: transformForClosure(static_cast<For_t*>(value), out); break; |
| @@ -1535,6 +1548,10 @@ private: | |||
| 1535 | transformTblCompReturn(comp, out); | 1548 | transformTblCompReturn(comp, out); |
| 1536 | return; | 1549 | return; |
| 1537 | } | 1550 | } |
| 1551 | if (auto with = simpleValue->value.as<With_t>()) { | ||
| 1552 | transformWith(with, out, nullptr, true); | ||
| 1553 | return; | ||
| 1554 | } | ||
| 1538 | if (auto classDecl = simpleValue->value.as<ClassDecl_t>()) { | 1555 | if (auto classDecl = simpleValue->value.as<ClassDecl_t>()) { |
| 1539 | transformClassDecl(classDecl, out, ExpUsage::Return); | 1556 | transformClassDecl(classDecl, out, ExpUsage::Return); |
| 1540 | return; | 1557 | return; |
| @@ -1579,15 +1596,15 @@ private: | |||
| 1579 | if (!argsDef->defList) { | 1596 | if (!argsDef->defList) { |
| 1580 | out.push_back(Empty); | 1597 | out.push_back(Empty); |
| 1581 | out.push_back(Empty); | 1598 | out.push_back(Empty); |
| 1582 | return; | 1599 | } else { |
| 1600 | transformFnArgDefList(argsDef->defList, out); | ||
| 1583 | } | 1601 | } |
| 1584 | transformFnArgDefList(argsDef->defList, out); | ||
| 1585 | if (argsDef->shadowOption) { | 1602 | if (argsDef->shadowOption) { |
| 1586 | transform_outer_var_shadow(argsDef->shadowOption, out); | 1603 | transform_outer_var_shadow(argsDef->shadowOption); |
| 1587 | } | 1604 | } |
| 1588 | } | 1605 | } |
| 1589 | 1606 | ||
| 1590 | void transform_outer_var_shadow(outer_var_shadow_t* shadow, str_list& out) { | 1607 | void transform_outer_var_shadow(outer_var_shadow_t* shadow) { |
| 1591 | markVarShadowed(); | 1608 | markVarShadowed(); |
| 1592 | if (shadow->varList) { | 1609 | if (shadow->varList) { |
| 1593 | for (auto name : shadow->varList->names.objects()) { | 1610 | for (auto name : shadow->varList->names.objects()) { |
| @@ -1752,7 +1769,12 @@ private: | |||
| 1752 | _buf << indent(-1) << "do"sv << nll(chainValue); | 1769 | _buf << indent(-1) << "do"sv << nll(chainValue); |
| 1753 | } | 1770 | } |
| 1754 | _buf << indent() << "local "sv << baseVar << " = "sv << caller << nll(chainValue); | 1771 | _buf << indent() << "local "sv << baseVar << " = "sv << caller << nll(chainValue); |
| 1755 | _buf << indent() << "local "sv << fnVar << " = "sv << baseVar << "."sv << funcName << nll(chainValue); | 1772 | _buf << indent() << "local "sv << fnVar << " = "sv << baseVar; |
| 1773 | if (State::luaKeywords.find(funcName) != State::luaKeywords.end()) { | ||
| 1774 | _buf << "[\""sv << funcName << "\"]" << nll(chainValue); | ||
| 1775 | } else { | ||
| 1776 | _buf << "."sv << funcName << nll(chainValue); | ||
| 1777 | } | ||
| 1756 | switch (usage) { | 1778 | switch (usage) { |
| 1757 | case ExpUsage::Return: | 1779 | case ExpUsage::Return: |
| 1758 | _buf << indent() << "return function(...)" << nll(chainValue); | 1780 | _buf << indent() << "return function(...)" << nll(chainValue); |
| @@ -1841,7 +1863,8 @@ private: | |||
| 1841 | } | 1863 | } |
| 1842 | 1864 | ||
| 1843 | void transformColonChainItem(ColonChainItem_t* colonChainItem, str_list& out) { | 1865 | void transformColonChainItem(ColonChainItem_t* colonChainItem, str_list& out) { |
| 1844 | out.push_back(s(colonChainItem->switchToDot ? "."sv : ":"sv) + toString(colonChainItem->name)); | 1866 | auto name = toString(colonChainItem->name); |
| 1867 | out.push_back(s(colonChainItem->switchToDot ? "."sv : ":"sv) + name); | ||
| 1845 | } | 1868 | } |
| 1846 | 1869 | ||
| 1847 | void transformSlice(Slice_t* slice, str_list& out) { | 1870 | void transformSlice(Slice_t* slice, str_list& out) { |
| @@ -1899,7 +1922,15 @@ private: | |||
| 1899 | break; | 1922 | break; |
| 1900 | } | 1923 | } |
| 1901 | } | 1924 | } |
| 1902 | transformStatement(comp->value.to<Statement_t>(), temp); | 1925 | if (auto stmt = comp->value.as<Statement_t>()) { |
| 1926 | transformStatement(stmt, temp); | ||
| 1927 | } else if (auto exp = comp->value.as<Exp_t>()) { | ||
| 1928 | auto expList = new_ptr<ExpList_t>(); | ||
| 1929 | expList->exprs.push_back(exp); | ||
| 1930 | auto statement = new_ptr<Statement_t>(); | ||
| 1931 | statement->content.set(expList); | ||
| 1932 | transformStatement(statement, temp); | ||
| 1933 | } | ||
| 1903 | auto value = temp.back(); | 1934 | auto value = temp.back(); |
| 1904 | temp.pop_back(); | 1935 | temp.pop_back(); |
| 1905 | _buf << join(temp) << value; | 1936 | _buf << join(temp) << value; |
| @@ -2306,10 +2337,10 @@ private: | |||
| 2306 | str_list temp; | 2337 | str_list temp; |
| 2307 | std::string accum = getUnusedName("_accum_"); | 2338 | std::string accum = getUnusedName("_accum_"); |
| 2308 | std::string len = getUnusedName("_len_"); | 2339 | std::string len = getUnusedName("_len_"); |
| 2309 | addToScope(accum); | ||
| 2310 | addToScope(len); | ||
| 2311 | _buf << "(function()"sv << nll(forEach); | 2340 | _buf << "(function()"sv << nll(forEach); |
| 2312 | pushScope(); | 2341 | pushScope(); |
| 2342 | addToScope(accum); | ||
| 2343 | addToScope(len); | ||
| 2313 | _buf << indent() << "local "sv << accum << " = { }"sv << nll(forEach); | 2344 | _buf << indent() << "local "sv << accum << " = { }"sv << nll(forEach); |
| 2314 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); | 2345 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); |
| 2315 | temp.push_back(clearBuf()); | 2346 | temp.push_back(clearBuf()); |
| @@ -2599,9 +2630,7 @@ private: | |||
| 2599 | temp.push_back(indent() + s("local "sv) + parentVar + s(" = "sv) + parent + nll(classDecl)); | 2630 | temp.push_back(indent() + s("local "sv) + parentVar + s(" = "sv) + parent + nll(classDecl)); |
| 2600 | } | 2631 | } |
| 2601 | auto baseVar = getUnusedName("_base_"sv); | 2632 | auto baseVar = getUnusedName("_base_"sv); |
| 2602 | auto selfVar = getUnusedName("_self_"sv); | ||
| 2603 | addToScope(baseVar); | 2633 | addToScope(baseVar); |
| 2604 | addToScope(selfVar); | ||
| 2605 | temp.push_back(indent() + s("local "sv) + baseVar + s(" = "sv)); | 2634 | temp.push_back(indent() + s("local "sv) + baseVar + s(" = "sv)); |
| 2606 | str_list builtins; | 2635 | str_list builtins; |
| 2607 | str_list commons; | 2636 | str_list commons; |
| @@ -2702,9 +2731,13 @@ private: | |||
| 2702 | _buf << indent(1) << "__index = "sv << baseVar << ","sv << nll(classDecl); | 2731 | _buf << indent(1) << "__index = "sv << baseVar << ","sv << nll(classDecl); |
| 2703 | } | 2732 | } |
| 2704 | _buf << indent(1) << "__call = function(cls, ...)"sv << nll(classDecl); | 2733 | _buf << indent(1) << "__call = function(cls, ...)"sv << nll(classDecl); |
| 2705 | _buf << indent(2) << "local " << selfVar << " = setmetatable({}, "sv << baseVar << ")"sv << nll(classDecl); | 2734 | pushScope(); |
| 2706 | _buf << indent(2) << "cls.__init("sv << selfVar << ", ...)"sv << nll(classDecl); | 2735 | auto selfVar = getUnusedName("_self_"sv); |
| 2707 | _buf << indent(2) << "return "sv << selfVar << nll(classDecl); | 2736 | addToScope(selfVar); |
| 2737 | _buf << indent(1) << "local " << selfVar << " = setmetatable({}, "sv << baseVar << ")"sv << nll(classDecl); | ||
| 2738 | _buf << indent(1) << "cls.__init("sv << selfVar << ", ...)"sv << nll(classDecl); | ||
| 2739 | _buf << indent(1) << "return "sv << selfVar << nll(classDecl); | ||
| 2740 | popScope(); | ||
| 2708 | _buf << indent(1) << "end"sv << nll(classDecl); | 2741 | _buf << indent(1) << "end"sv << nll(classDecl); |
| 2709 | _buf << indent() << "})"sv << nll(classDecl); | 2742 | _buf << indent() << "})"sv << nll(classDecl); |
| 2710 | _buf << indent() << baseVar << ".__class = "sv << classVar << nll(classDecl); | 2743 | _buf << indent() << baseVar << ".__class = "sv << classVar << nll(classDecl); |
| @@ -2846,7 +2879,17 @@ private: | |||
| 2846 | } | 2879 | } |
| 2847 | } | 2880 | } |
| 2848 | 2881 | ||
| 2849 | void transformWith(With_t* with, str_list& out, ExpList_t* assignList = nullptr) { | 2882 | void transformWithClosure(With_t* with, str_list& out) { |
| 2883 | str_list temp; | ||
| 2884 | temp.push_back(s("(function()"sv) + nll(with)); | ||
| 2885 | pushScope(); | ||
| 2886 | transformWith(with, temp, nullptr, true); | ||
| 2887 | popScope(); | ||
| 2888 | temp.push_back(indent() + s("end)()"sv)); | ||
| 2889 | out.push_back(join(temp)); | ||
| 2890 | } | ||
| 2891 | |||
| 2892 | void transformWith(With_t* with, str_list& out, ExpList_t* assignList = nullptr, bool returnValue = false) { | ||
| 2850 | str_list temp; | 2893 | str_list temp; |
| 2851 | std::string withVar; | 2894 | std::string withVar; |
| 2852 | bool scoped = false; | 2895 | bool scoped = false; |
| @@ -2926,6 +2969,12 @@ private: | |||
| 2926 | assignment->target.set(assign); | 2969 | assignment->target.set(assign); |
| 2927 | transformAssignment(assignment, temp); | 2970 | transformAssignment(assignment, temp); |
| 2928 | } | 2971 | } |
| 2972 | if (returnValue) { | ||
| 2973 | auto stmt = lastStatementFrom(with->body); | ||
| 2974 | if (!stmt->content.is<Return_t>()) { | ||
| 2975 | temp.push_back(indent() + s("return "sv) + withVar + nll(with)); | ||
| 2976 | } | ||
| 2977 | } | ||
| 2929 | if (scoped) { | 2978 | if (scoped) { |
| 2930 | popScope(); | 2979 | popScope(); |
| 2931 | temp.push_back(indent() + s("end"sv) + nll(with)); | 2980 | temp.push_back(indent() + s("end"sv) + nll(with)); |
| @@ -2992,6 +3041,10 @@ private: | |||
| 2992 | } | 3041 | } |
| 2993 | 3042 | ||
| 2994 | void transformTable(ast_node* table, const std::list<ast_node*>& pairs, str_list& out) { | 3043 | void transformTable(ast_node* table, const std::list<ast_node*>& pairs, str_list& out) { |
| 3044 | if (pairs.empty()) { | ||
| 3045 | out.push_back(s("{ }"sv)); | ||
| 3046 | return; | ||
| 3047 | } | ||
| 2995 | str_list temp; | 3048 | str_list temp; |
| 2996 | pushScope(); | 3049 | pushScope(); |
| 2997 | for (auto pair : pairs) { | 3050 | for (auto pair : pairs) { |
| @@ -3386,13 +3439,346 @@ const std::string MoonCompliler::Empty; | |||
| 3386 | int main() | 3439 | int main() |
| 3387 | { | 3440 | { |
| 3388 | std::string s = R"TestCodesHere( | 3441 | std::string s = R"TestCodesHere( |
| 3442 | Dorothy builtin.ImGui | ||
| 3443 | import Set,Path from require "Utils" | ||
| 3444 | LintGlobal = require "LintGlobal" | ||
| 3445 | moonscript = require "moonscript" | ||
| 3446 | |||
| 3447 | LoadFontTTF "Font/DroidSansFallback.ttf", 20, "Chinese" | ||
| 3448 | |||
| 3449 | moduleCache = {} | ||
| 3450 | oldRequire = _G.require | ||
| 3451 | newRequire = (path)-> | ||
| 3452 | loaded = package.loaded[path] | ||
| 3453 | if not loaded | ||
| 3454 | table.insert moduleCache,path | ||
| 3455 | return oldRequire path | ||
| 3456 | loaded | ||
| 3457 | _G.require = newRequire | ||
| 3458 | builtin.require = newRequire | ||
| 3459 | |||
| 3460 | allowedUseOfGlobals = Set { | ||
| 3461 | } | ||
| 3389 | 3462 | ||
| 3390 | do | 3463 | LintMoonGlobals = (moonCodes,entry)-> |
| 3391 | a = -> | 3464 | globals,err = LintGlobal moonCodes |
| 3392 | with something | 3465 | if not globals |
| 3393 | print .hello | 3466 | error "Compile failed in #{entry}\n#{err}" |
| 3394 | print hi | 3467 | requireModules = {} |
| 3395 | print "world" | 3468 | withImGui = false |
| 3469 | withPlatformer = false | ||
| 3470 | importCodes = table.concat ( | ||
| 3471 | for importLine in moonCodes\gmatch "Dorothy%s*%(?([^%)!\r\n]*)%s*[%)!]?" | ||
| 3472 | continue if importLine == "" | ||
| 3473 | importLine | ||
| 3474 | ), "," | ||
| 3475 | importItems = if importCodes | ||
| 3476 | for item in importCodes\gmatch "%s*([^,\n\r]+)%s*" | ||
| 3477 | getImport = loadstring "return #{item}" | ||
| 3478 | importItem = if getImport then getImport! else nil | ||
| 3479 | continue if not importItem or "table" ~= type importItem | ||
| 3480 | {importItem, item} | ||
| 3481 | else {} | ||
| 3482 | importSet = {} | ||
| 3483 | for name,_ in pairs globals | ||
| 3484 | if not allowedUseOfGlobals[name] | ||
| 3485 | if builtin[name] | ||
| 3486 | table.insert requireModules, "local #{name} = require(\"#{name}\")" | ||
| 3487 | else | ||
| 3488 | findModule = false | ||
| 3489 | for i,importItem in ipairs importItems | ||
| 3490 | if importItem[1][name] ~= nil | ||
| 3491 | moduleName = "_module_#{i-1}" | ||
| 3492 | if not importSet[importItem[1]] | ||
| 3493 | importSet[importItem[1]] = true | ||
| 3494 | table.insert requireModules, "local #{moduleName} = #{importItem[2]}" | ||
| 3495 | table.insert requireModules, "local #{name} = #{moduleName}.#{name}" | ||
| 3496 | findModule = true | ||
| 3497 | break | ||
| 3498 | if not findModule | ||
| 3499 | error "Used invalid global value \"#{name}\" in \"#{entry}\"." | ||
| 3500 | table.concat requireModules, "\n" | ||
| 3501 | |||
| 3502 | totalFiles = 0 | ||
| 3503 | totalMoonTime = 0 | ||
| 3504 | totalXmlTime = 0 | ||
| 3505 | totalMinifyTime = 0 | ||
| 3506 | compile = (dir,clean,minify)-> | ||
| 3507 | {:ParseLua} = require "luaminify.ParseLua" | ||
| 3508 | FormatMini = require "luaminify.FormatMini" | ||
| 3509 | files = Path.getAllFiles dir, {"moon","xml"} | ||
| 3510 | for file in *files | ||
| 3511 | path = Path.getPath file | ||
| 3512 | name = Path.getName file | ||
| 3513 | isXml = "xml" == Path.getExtension file | ||
| 3514 | compileFunc = isXml and xmltolua or moonscript.to_lua | ||
| 3515 | requires = nil | ||
| 3516 | if not clean | ||
| 3517 | sourceCodes = Content\loadAsync "#{dir}/#{file}" | ||
| 3518 | requires = LintMoonGlobals sourceCodes, file unless isXml | ||
| 3519 | startTime = App.eclapsedTime | ||
| 3520 | codes,err = compileFunc sourceCodes | ||
| 3521 | if isXml | ||
| 3522 | totalXmlTime += App.eclapsedTime - startTime | ||
| 3523 | else | ||
| 3524 | totalMoonTime += App.eclapsedTime - startTime | ||
| 3525 | startTime = App.eclapsedTime | ||
| 3526 | if not codes | ||
| 3527 | print "Compile errors in #{file}." | ||
| 3528 | print err | ||
| 3529 | return false | ||
| 3530 | else | ||
| 3531 | codes = requires..codes\gsub "Dorothy%([^%)]*%)","" unless isXml | ||
| 3532 | if minify | ||
| 3533 | st, ast = ParseLua codes | ||
| 3534 | if not st | ||
| 3535 | print ast | ||
| 3536 | return false | ||
| 3537 | codes = FormatMini ast | ||
| 3538 | totalMinifyTime += App.eclapsedTime - startTime | ||
| 3539 | filePath = Content.writablePath..path | ||
| 3540 | Content\mkdir filePath | ||
| 3541 | filename = "#{filePath}#{name}.lua" | ||
| 3542 | Content\saveAsync filename,codes | ||
| 3543 | print "#{isXml and "Xml" or "Moon"} compiled: #{path}#{name}.#{isXml and "xml" or "moon"}" | ||
| 3544 | totalFiles += 1 | ||
| 3545 | else | ||
| 3546 | filePath = Content.writablePath..path | ||
| 3547 | Content\mkdir filePath | ||
| 3548 | filename = "#{filePath}#{name}.lua" | ||
| 3549 | if Content\exist filename | ||
| 3550 | print "#{isXml and "Xml" or "Moon"} cleaned: #{path}#{name}.lua" | ||
| 3551 | Content\remove filename | ||
| 3552 | if clean or minify | ||
| 3553 | files = Path.getAllFiles dir, "lua" | ||
| 3554 | for file in *files | ||
| 3555 | path = Path.getPath file | ||
| 3556 | name = Path.getName file | ||
| 3557 | if not clean | ||
| 3558 | sourceCodes = Content\loadAsync "#{dir}/#{file}" | ||
| 3559 | startTime = App.eclapsedTime | ||
| 3560 | st, ast = ParseLua sourceCodes | ||
| 3561 | if not st | ||
| 3562 | print ast | ||
| 3563 | return false | ||
| 3564 | codes = FormatMini ast | ||
| 3565 | totalMinifyTime += App.eclapsedTime - startTime | ||
| 3566 | filePath = Content.writablePath..path | ||
| 3567 | Content\mkdir filePath | ||
| 3568 | filename = "#{filePath}#{name}.lua" | ||
| 3569 | Content\saveAsync filename,codes | ||
| 3570 | print "Lua minified: #{path}#{name}.lua" | ||
| 3571 | totalFiles += 1 | ||
| 3572 | else | ||
| 3573 | filePath = Content.writablePath..path | ||
| 3574 | Content\mkdir filePath | ||
| 3575 | filename = "#{filePath}#{name}.lua" | ||
| 3576 | if Content\exist filename | ||
| 3577 | print "Lua cleaned: #{path}#{name}.lua" | ||
| 3578 | Content\remove filename | ||
| 3579 | return true | ||
| 3580 | |||
| 3581 | building = false | ||
| 3582 | |||
| 3583 | doCompile = (minify)-> | ||
| 3584 | return if building | ||
| 3585 | building = true | ||
| 3586 | totalFiles = 0 | ||
| 3587 | totalMoonTime = 0 | ||
| 3588 | totalXmlTime = 0 | ||
| 3589 | totalMinifyTime = 0 | ||
| 3590 | thread -> | ||
| 3591 | print "Output path: #{Content.writablePath}" | ||
| 3592 | xpcall (-> compile Content.assetPath\sub(1,-2),false,minify),(msg)-> | ||
| 3593 | msg = debug.traceback msg | ||
| 3594 | print msg | ||
| 3595 | building = false | ||
| 3596 | print string.format "Compile #{minify and 'and minify ' or ''}done. %d files in total.\nCompile time, Moon %.3fs, Xml %.3fs#{minify and ', Minify %.3fs' or ''}.\n",totalFiles,totalMoonTime,totalXmlTime,totalMinifyTime | ||
| 3597 | building = false | ||
| 3598 | |||
| 3599 | doClean = -> | ||
| 3600 | return if building | ||
| 3601 | building = true | ||
| 3602 | thread -> | ||
| 3603 | print "Clean path: #{Content.writablePath}" | ||
| 3604 | compile Content.assetPath\sub(1,-2),true | ||
| 3605 | print "Clean done.\n" | ||
| 3606 | building = false | ||
| 3607 | |||
| 3608 | isInEntry = true | ||
| 3609 | |||
| 3610 | allClear = -> | ||
| 3611 | for module in *moduleCache | ||
| 3612 | package.loaded[module] = nil | ||
| 3613 | moduleCache = {} | ||
| 3614 | with Director.ui | ||
| 3615 | \removeAllChildren! | ||
| 3616 | .userData = nil | ||
| 3617 | with Director.entry | ||
| 3618 | \removeAllChildren! | ||
| 3619 | .userData = nil | ||
| 3620 | with Director.postNode | ||
| 3621 | \removeAllChildren! | ||
| 3622 | .userData = nil | ||
| 3623 | Director\popCamera! | ||
| 3624 | Cache\unload! | ||
| 3625 | Entity\clear! | ||
| 3626 | Platformer.Data\clear! | ||
| 3627 | Platformer.UnitAction\clear! | ||
| 3628 | currentEntryName = nil | ||
| 3629 | isInEntry = true | ||
| 3630 | Audio\stopStream 0.2 | ||
| 3631 | |||
| 3632 | games = [Path.getName item for item in *Path.getFolders Content.assetPath.."Script/Game", {"xml","lua","moon"}] | ||
| 3633 | table.sort games | ||
| 3634 | examples = [Path.getName item for item in *Path.getAllFiles Content.assetPath.."Script/Example", {"xml","lua","moon"}] | ||
| 3635 | table.sort examples | ||
| 3636 | tests = [Path.getName item for item in *Path.getAllFiles Content.assetPath.."Script/Test", {"xml","lua","moon"}] | ||
| 3637 | table.sort tests | ||
| 3638 | currentEntryName = nil | ||
| 3639 | allNames = for game in *games do "Game/#{game}/init" | ||
| 3640 | for example in *examples do table.insert allNames,"Example/#{example}" | ||
| 3641 | for test in *tests do table.insert allNames,"Test/#{test}" | ||
| 3642 | |||
| 3643 | enterDemoEntry = (name)-> | ||
| 3644 | isInEntry = false | ||
| 3645 | xpcall (-> | ||
| 3646 | result = require name | ||
| 3647 | if "function" == type result | ||
| 3648 | result = result! | ||
| 3649 | Director.entry\addChild if tolua.cast result, "Node" | ||
| 3650 | result | ||
| 3651 | else | ||
| 3652 | Node! | ||
| 3653 | else | ||
| 3654 | Director.entry\addChild Node! | ||
| 3655 | currentEntryName = name | ||
| 3656 | ),(msg)-> | ||
| 3657 | msg = debug.traceback msg | ||
| 3658 | print msg | ||
| 3659 | allClear! | ||
| 3660 | |||
| 3661 | showEntry = false | ||
| 3662 | |||
| 3663 | thread -> | ||
| 3664 | {:width,:height} = App.visualSize | ||
| 3665 | scale = App.deviceRatio*0.7*math.min(width,height)/760 | ||
| 3666 | with Sprite GetDorothySSRHappyWhite scale | ||
| 3667 | \addTo Director.entry | ||
| 3668 | sleep 1.0 | ||
| 3669 | \removeFromParent! | ||
| 3670 | showEntry = true | ||
| 3671 | Director.clearColor = Color 0xff1a1a1a | ||
| 3672 | |||
| 3673 | showStats = false | ||
| 3674 | showLog = false | ||
| 3675 | showFooter = true | ||
| 3676 | scaleContent = false | ||
| 3677 | footerFocus = false | ||
| 3678 | screenScale = 2 -- App.deviceRatio | ||
| 3679 | threadLoop -> | ||
| 3680 | return unless showEntry | ||
| 3681 | left = Keyboard\isKeyDown "Left" | ||
| 3682 | right = Keyboard\isKeyDown "Right" | ||
| 3683 | App\shutdown! if Keyboard\isKeyDown "Escape" | ||
| 3684 | {:width,:height} = App.visualSize | ||
| 3685 | SetNextWindowSize Vec2(190,50) | ||
| 3686 | SetNextWindowPos Vec2(width-190,height-50) | ||
| 3687 | if width >= 600 | ||
| 3688 | if not footerFocus | ||
| 3689 | footerFocus = true | ||
| 3690 | SetNextWindowFocus! | ||
| 3691 | PushStyleColor "WindowBg", Color(0x0), -> | ||
| 3692 | Begin "Show", "NoTitleBar|NoResize|NoMove|NoCollapse|NoSavedSettings", -> | ||
| 3693 | Columns 2,false | ||
| 3694 | if showFooter | ||
| 3695 | changed, scaleContent = Checkbox string.format("%.1fx",screenScale), scaleContent | ||
| 3696 | View.scale = scaleContent and screenScale or 1 if changed | ||
| 3697 | else | ||
| 3698 | Dummy Vec2 10,30 | ||
| 3699 | SameLine! | ||
| 3700 | NextColumn! | ||
| 3701 | _, showFooter = Checkbox "Footer", showFooter | ||
| 3702 | elseif footerFocus | ||
| 3703 | footerFocus = false | ||
| 3704 | return unless showFooter | ||
| 3705 | SetNextWindowSize Vec2(width,60) | ||
| 3706 | SetNextWindowPos Vec2(0,height-60) | ||
| 3707 | Begin "Footer", "NoTitleBar|NoResize|NoMove|NoCollapse|NoBringToFrontOnFocus|NoSavedSettings", -> | ||
| 3708 | Separator! | ||
| 3709 | _, showStats = Checkbox "Stats", showStats | ||
| 3710 | SameLine! | ||
| 3711 | _, showLog = Checkbox "Log", showLog | ||
| 3712 | SameLine! | ||
| 3713 | if isInEntry | ||
| 3714 | OpenPopup "build" if Button "Build", Vec2(70,30) | ||
| 3715 | BeginPopup "build", -> | ||
| 3716 | doCompile false if Selectable "Compile" | ||
| 3717 | Separator! | ||
| 3718 | doCompile true if Selectable "Minify" | ||
| 3719 | Separator! | ||
| 3720 | doClean! if Selectable "Clean" | ||
| 3721 | else | ||
| 3722 | SameLine! | ||
| 3723 | allClear! if Button "Home", Vec2(70,30) | ||
| 3724 | currentIndex = 1 | ||
| 3725 | for i,name in ipairs allNames | ||
| 3726 | if currentEntryName == name | ||
| 3727 | currentIndex = i | ||
| 3728 | SameLine! | ||
| 3729 | if currentIndex > 1 | ||
| 3730 | if Button("Prev", Vec2(70,30)) or left | ||
| 3731 | allClear! | ||
| 3732 | isInEntry = false | ||
| 3733 | thread -> enterDemoEntry allNames[currentIndex-1] | ||
| 3734 | else Dummy Vec2 70,30 | ||
| 3735 | SameLine! | ||
| 3736 | if currentIndex < #allNames | ||
| 3737 | if Button("Next", Vec2(70,30)) or right | ||
| 3738 | allClear! | ||
| 3739 | isInEntry = false | ||
| 3740 | thread -> enterDemoEntry allNames[currentIndex+1] | ||
| 3741 | else Dummy Vec2 70,30 | ||
| 3742 | if showStats | ||
| 3743 | SetNextWindowPos Vec2(0,height-65-296), "FirstUseEver" | ||
| 3744 | ShowStats! | ||
| 3745 | if showLog | ||
| 3746 | SetNextWindowPos Vec2(width-400,height-65-300), "FirstUseEver" | ||
| 3747 | ShowLog! | ||
| 3748 | |||
| 3749 | threadLoop -> | ||
| 3750 | return unless showEntry | ||
| 3751 | return unless isInEntry | ||
| 3752 | {:width,:height} = App.visualSize | ||
| 3753 | SetNextWindowPos Vec2.zero | ||
| 3754 | SetNextWindowSize Vec2(width,53) | ||
| 3755 | PushStyleColor "TitleBgActive", Color(0xcc000000), -> | ||
| 3756 | Begin "Dorothy Dev", "NoResize|NoMove|NoCollapse|NoBringToFrontOnFocus|NoSavedSettings", -> | ||
| 3757 | Separator! | ||
| 3758 | SetNextWindowPos Vec2(0,53) | ||
| 3759 | SetNextWindowSize Vec2(width,height-107) | ||
| 3760 | PushStyleColor "WindowBg",Color(0x0), -> | ||
| 3761 | Begin "Content", "NoTitleBar|NoResize|NoMove|NoCollapse|NoBringToFrontOnFocus|NoSavedSettings", -> | ||
| 3762 | TextColored Color(0xff00ffff), "Game Demos" | ||
| 3763 | Columns math.max(math.floor(width/200),1), false | ||
| 3764 | for game in *games | ||
| 3765 | if Button game, Vec2(-1,40) | ||
| 3766 | enterDemoEntry "Game/#{game}/init" | ||
| 3767 | NextColumn! | ||
| 3768 | Columns 1, false | ||
| 3769 | TextColored Color(0xff00ffff), "Examples" | ||
| 3770 | Columns math.max(math.floor(width/200),1), false | ||
| 3771 | for example in *examples | ||
| 3772 | if Button example, Vec2(-1,40) | ||
| 3773 | enterDemoEntry "Example/#{example}" | ||
| 3774 | NextColumn! | ||
| 3775 | Columns 1, false | ||
| 3776 | TextColored Color(0xff00ffff), "Tests" | ||
| 3777 | Columns math.max(math.floor(width/200),1), false | ||
| 3778 | for test in *tests | ||
| 3779 | if Button test, Vec2(-1,40) | ||
| 3780 | enterDemoEntry "Test/#{test}" | ||
| 3781 | NextColumn! | ||
| 3396 | )TestCodesHere"; | 3782 | )TestCodesHere"; |
| 3397 | MoonCompliler{}.complile(s); | 3783 | MoonCompliler{}.complile(s); |
| 3398 | return 0; | 3784 | return 0; |
diff --git a/MoonParser/moon_ast.h b/MoonParser/moon_ast.h index d4ade53..795c0c8 100644 --- a/MoonParser/moon_ast.h +++ b/MoonParser/moon_ast.h | |||
| @@ -477,11 +477,9 @@ AST_LEAF(BreakLoop, "BreakLoop"_id) | |||
| 477 | AST_END(BreakLoop) | 477 | AST_END(BreakLoop) |
| 478 | 478 | ||
| 479 | AST_NODE(Statement, "Statement"_id) | 479 | AST_NODE(Statement, "Statement"_id) |
| 480 | ast_ptr<ast_node> content; /* | 480 | ast_sel<Import_t, While_t, For_t, ForEach_t, |
| 481 | Import_t | While_t | With_t | For_t | ForEach_t | | 481 | Return_t, Local_t, Export_t, BreakLoop_t, |
| 482 | Return_t | Local_t | Export_t | BreakLoop_t | | 482 | Assignment_t, ExpList_t> content; |
| 483 | Assignment_t | ExpList_t | ||
| 484 | */ | ||
| 485 | ast_ptr<statement_appendix_t, true> appendix; | 483 | ast_ptr<statement_appendix_t, true> appendix; |
| 486 | AST_END(Statement) | 484 | AST_END(Statement) |
| 487 | 485 | ||
diff --git a/MoonParser/moon_parser.cpp b/MoonParser/moon_parser.cpp index ad86020..d709e29 100644 --- a/MoonParser/moon_parser.cpp +++ b/MoonParser/moon_parser.cpp | |||
| @@ -15,7 +15,8 @@ std::unordered_set<std::string> State::keywords = { | |||
| 15 | "repeat", "return", "then", "true", "until", | 15 | "repeat", "return", "then", "true", "until", |
| 16 | "while", // Lua keywords | 16 | "while", // Lua keywords |
| 17 | "class", "continue", "export", "extends", | 17 | "class", "continue", "export", "extends", |
| 18 | "import", "switch", "unless", "using", "with" // Moon keywords | 18 | "import", "switch", "when", "unless", "using", |
| 19 | "with" // Moon keywords | ||
| 19 | }; | 20 | }; |
| 20 | 21 | ||
| 21 | rule plain_space = *set(" \t"); | 22 | rule plain_space = *set(" \t"); |
| @@ -487,7 +488,7 @@ rule unless_line = key("unless") >> Exp; | |||
| 487 | rule statement_appendix = (if_else_line | unless_line | CompInner) >> Space; | 488 | rule statement_appendix = (if_else_line | unless_line | CompInner) >> Space; |
| 488 | rule Statement = | 489 | rule Statement = |
| 489 | ( | 490 | ( |
| 490 | Import | While | With | For | ForEach | | 491 | Import | While | For | ForEach | |
| 491 | Return | Local | Export | Space >> BreakLoop | | 492 | Return | Local | Export | Space >> BreakLoop | |
| 492 | Assignment | ExpList | 493 | Assignment | ExpList |
| 493 | ) >> Space >> | 494 | ) >> Space >> |
