summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2019-10-07 20:05:59 +0800
committerLi Jin <dragon-fly@qq.com>2019-10-07 20:05:59 +0800
commit726fee3152c81fdac7e3ad5f663bfbea8f99ddd8 (patch)
tree203066824db5ad76520ed743c2af4005237d0078
parent055fcb596781a8488afeb0030e9ef4295e3d7017 (diff)
downloadyuescript-726fee3152c81fdac7e3ad5f663bfbea8f99ddd8.tar.gz
yuescript-726fee3152c81fdac7e3ad5f663bfbea8f99ddd8.tar.bz2
yuescript-726fee3152c81fdac7e3ad5f663bfbea8f99ddd8.zip
fixing compile issues.
-rw-r--r--MoonParser/moon_ast.cpp524
-rw-r--r--MoonParser/moon_ast.h8
-rw-r--r--MoonParser/moon_parser.cpp5
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;
3386int main() 3439int main()
3387{ 3440{
3388 std::string s = R"TestCodesHere( 3441 std::string s = R"TestCodesHere(
3442Dorothy builtin.ImGui
3443import Set,Path from require "Utils"
3444LintGlobal = require "LintGlobal"
3445moonscript = require "moonscript"
3446
3447LoadFontTTF "Font/DroidSansFallback.ttf", 20, "Chinese"
3448
3449moduleCache = {}
3450oldRequire = _G.require
3451newRequire = (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
3458builtin.require = newRequire
3459
3460allowedUseOfGlobals = Set {
3461}
3389 3462
3390do 3463LintMoonGlobals = (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
3502totalFiles = 0
3503totalMoonTime = 0
3504totalXmlTime = 0
3505totalMinifyTime = 0
3506compile = (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
3581building = false
3582
3583doCompile = (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
3599doClean = ->
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
3608isInEntry = true
3609
3610allClear = ->
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
3632games = [Path.getName item for item in *Path.getFolders Content.assetPath.."Script/Game", {"xml","lua","moon"}]
3633table.sort games
3634examples = [Path.getName item for item in *Path.getAllFiles Content.assetPath.."Script/Example", {"xml","lua","moon"}]
3635table.sort examples
3636tests = [Path.getName item for item in *Path.getAllFiles Content.assetPath.."Script/Test", {"xml","lua","moon"}]
3637table.sort tests
3638currentEntryName = nil
3639allNames = for game in *games do "Game/#{game}/init"
3640for example in *examples do table.insert allNames,"Example/#{example}"
3641for test in *tests do table.insert allNames,"Test/#{test}"
3642
3643enterDemoEntry = (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
3661showEntry = false
3662
3663thread ->
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
3673showStats = false
3674showLog = false
3675showFooter = true
3676scaleContent = false
3677footerFocus = false
3678screenScale = 2 -- App.deviceRatio
3679threadLoop ->
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
3749threadLoop ->
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)
477AST_END(BreakLoop) 477AST_END(BreakLoop)
478 478
479AST_NODE(Statement, "Statement"_id) 479AST_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;
486AST_END(Statement) 484AST_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
21rule plain_space = *set(" \t"); 22rule plain_space = *set(" \t");
@@ -487,7 +488,7 @@ rule unless_line = key("unless") >> Exp;
487rule statement_appendix = (if_else_line | unless_line | CompInner) >> Space; 488rule statement_appendix = (if_else_line | unless_line | CompInner) >> Space;
488rule Statement = 489rule 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 >>