diff options
author | Li Jin <dragon-fly@qq.com> | 2020-01-18 18:15:24 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2020-01-18 18:15:24 +0800 |
commit | 8d1af508f4173e4af6a4ea98584c1a86619f6a20 (patch) | |
tree | 0264c4b01f1152d8114cf46aea6fd773276c0b01 /src | |
parent | f53ccb373efbf6f6f40284111df309e351c2c18f (diff) | |
download | yuescript-8d1af508f4173e4af6a4ea98584c1a86619f6a20.tar.gz yuescript-8d1af508f4173e4af6a4ea98584c1a86619f6a20.tar.bz2 yuescript-8d1af508f4173e4af6a4ea98584c1a86619f6a20.zip |
fix Moonscript issue 122, add support for ? operator.
Diffstat (limited to 'src')
-rw-r--r-- | src/MoonP/ast.hpp | 6 | ||||
-rw-r--r-- | src/MoonP/moon_ast.cpp | 1 | ||||
-rw-r--r-- | src/MoonP/moon_ast.h | 5 | ||||
-rw-r--r-- | src/MoonP/moon_compiler.cpp | 508 | ||||
-rw-r--r-- | src/MoonP/moon_parser.cpp | 15 | ||||
-rw-r--r-- | src/moonc.cpp | 12 |
6 files changed, 377 insertions, 170 deletions
diff --git a/src/MoonP/ast.hpp b/src/MoonP/ast.hpp index f2ef76c..0b5ffca 100644 --- a/src/MoonP/ast.hpp +++ b/src/MoonP/ast.hpp | |||
@@ -392,6 +392,12 @@ public: | |||
392 | node->release(); | 392 | node->release(); |
393 | } | 393 | } |
394 | 394 | ||
395 | void pop_back() { | ||
396 | auto node = m_objects.back(); | ||
397 | m_objects.pop_back(); | ||
398 | node->release(); | ||
399 | } | ||
400 | |||
395 | const node_container& objects() const { | 401 | const node_container& objects() const { |
396 | return m_objects; | 402 | return m_objects; |
397 | } | 403 | } |
diff --git a/src/MoonP/moon_ast.cpp b/src/MoonP/moon_ast.cpp index 0ccd0ed..f3fe31e 100644 --- a/src/MoonP/moon_ast.cpp +++ b/src/MoonP/moon_ast.cpp | |||
@@ -79,6 +79,7 @@ AST_IMPL(ColonChainItem) | |||
79 | AST_IMPL(default_value) | 79 | AST_IMPL(default_value) |
80 | AST_IMPL(Slice) | 80 | AST_IMPL(Slice) |
81 | AST_IMPL(Invoke) | 81 | AST_IMPL(Invoke) |
82 | AST_IMPL(existential_op) | ||
82 | AST_IMPL(TableLit) | 83 | AST_IMPL(TableLit) |
83 | AST_IMPL(TableBlock) | 84 | AST_IMPL(TableBlock) |
84 | AST_IMPL(class_member_list) | 85 | AST_IMPL(class_member_list) |
diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index a614465..8b80af3 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h | |||
@@ -407,11 +407,14 @@ AST_NODE(Invoke, "Invoke"_id) | |||
407 | AST_MEMBER(Invoke, &sep, &args) | 407 | AST_MEMBER(Invoke, &sep, &args) |
408 | AST_END(Invoke) | 408 | AST_END(Invoke) |
409 | 409 | ||
410 | AST_LEAF(existential_op, "existential_op"_id) | ||
411 | AST_END(existential_op) | ||
412 | |||
410 | class InvokeArgs_t; | 413 | class InvokeArgs_t; |
411 | 414 | ||
412 | AST_NODE(ChainValue, "ChainValue"_id) | 415 | AST_NODE(ChainValue, "ChainValue"_id) |
413 | ast_ptr<true, Seperator_t> sep; | 416 | ast_ptr<true, Seperator_t> sep; |
414 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t> items; | 417 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, existential_op_t> items; |
415 | AST_MEMBER(ChainValue, &sep, &items) | 418 | AST_MEMBER(ChainValue, &sep, &items) |
416 | AST_END(ChainValue) | 419 | AST_END(ChainValue) |
417 | 420 | ||
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index d30f413..9164f6a 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp | |||
@@ -15,6 +15,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI | |||
15 | #include <memory> | 15 | #include <memory> |
16 | #include <sstream> | 16 | #include <sstream> |
17 | #include <string_view> | 17 | #include <string_view> |
18 | #include <iostream> | ||
18 | using namespace std::string_view_literals; | 19 | using namespace std::string_view_literals; |
19 | #include "MoonP/parser.hpp" | 20 | #include "MoonP/parser.hpp" |
20 | #include "MoonP/moon_ast.h" | 21 | #include "MoonP/moon_ast.h" |
@@ -426,6 +427,35 @@ private: | |||
426 | return ast_is<InvokeArgs_t, Invoke_t>(chainValue->items.back()); | 427 | return ast_is<InvokeArgs_t, Invoke_t>(chainValue->items.back()); |
427 | } | 428 | } |
428 | 429 | ||
430 | bool isSpecialChainValue(ChainValue_t* chainValue) { | ||
431 | if (ast_is<ColonChainItem_t>(chainValue->items.back())) { | ||
432 | return true; | ||
433 | } | ||
434 | for (auto item : chainValue->items.objects()) { | ||
435 | if (auto colonChain = ast_cast<ColonChainItem_t>(item)) { | ||
436 | if (ast_is<LuaKeyword_t>(colonChain->name)) { | ||
437 | return true; | ||
438 | } | ||
439 | } else if (ast_is<existential_op_t>(item) && item != chainValue->items.back()) { | ||
440 | return true; | ||
441 | } | ||
442 | } | ||
443 | return false; | ||
444 | } | ||
445 | |||
446 | std::string singleVariableFrom(ChainValue_t* chainValue) { | ||
447 | BLOCK_START | ||
448 | BREAK_IF(!chainValue); | ||
449 | BREAK_IF(chainValue->items.size() != 1); | ||
450 | auto callable = ast_cast<Callable_t>(chainValue->items.front()); | ||
451 | BREAK_IF(!callable || !(callable->item.is<Variable_t>() || callable->getByPath<SelfName_t,self_t>())); | ||
452 | str_list tmp; | ||
453 | transformCallable(callable, tmp); | ||
454 | return tmp.back(); | ||
455 | BLOCK_END | ||
456 | return Empty; | ||
457 | } | ||
458 | |||
429 | std::string singleVariableFrom(ast_node* expList) { | 459 | std::string singleVariableFrom(ast_node* expList) { |
430 | if (!ast_is<Exp_t, ExpList_t>(expList)) return Empty; | 460 | if (!ast_is<Exp_t, ExpList_t>(expList)) return Empty; |
431 | BLOCK_START | 461 | BLOCK_START |
@@ -435,7 +465,7 @@ private: | |||
435 | BREAK_IF(!chainValue); | 465 | BREAK_IF(!chainValue); |
436 | BREAK_IF(chainValue->items.size() != 1); | 466 | BREAK_IF(chainValue->items.size() != 1); |
437 | auto callable = ast_cast<Callable_t>(chainValue->items.front()); | 467 | auto callable = ast_cast<Callable_t>(chainValue->items.front()); |
438 | BREAK_IF(!callable || !callable->item.is<Variable_t>()); | 468 | BREAK_IF(!callable || !(callable->item.is<Variable_t>() || callable->getByPath<SelfName_t,self_t>())); |
439 | str_list tmp; | 469 | str_list tmp; |
440 | transformCallable(callable, tmp); | 470 | transformCallable(callable, tmp); |
441 | return tmp.back(); | 471 | return tmp.back(); |
@@ -443,22 +473,6 @@ private: | |||
443 | return Empty; | 473 | return Empty; |
444 | } | 474 | } |
445 | 475 | ||
446 | bool isColonChain(ChainValue_t* chainValue) { | ||
447 | return ast_is<ColonChainItem_t>(chainValue->items.back()); | ||
448 | } | ||
449 | |||
450 | bool hasKeywordColonChainItem(ChainValue_t* chainValue) { | ||
451 | const auto& chainList = chainValue->items.objects(); | ||
452 | for (auto it = chainList.begin(); it != chainList.end(); ++it) { | ||
453 | if (auto colonItem = ast_cast<ColonChainItem_t>(*it)) { | ||
454 | if (colonItem->name.is<LuaKeyword_t>()) { | ||
455 | return true; | ||
456 | } | ||
457 | } | ||
458 | } | ||
459 | return false; | ||
460 | } | ||
461 | |||
462 | bool isAssignable(const node_container& chainItems) { | 476 | bool isAssignable(const node_container& chainItems) { |
463 | if (chainItems.size() == 1) { | 477 | if (chainItems.size() == 1) { |
464 | auto firstItem = chainItems.back(); | 478 | auto firstItem = chainItems.back(); |
@@ -539,7 +553,7 @@ private: | |||
539 | } | 553 | } |
540 | auto line = _converter.to_bytes(std::wstring(begin, end)); | 554 | auto line = _converter.to_bytes(std::wstring(begin, end)); |
541 | int oldCol = loc->m_begin.m_col; | 555 | int oldCol = loc->m_begin.m_col; |
542 | int col = loc->m_begin.m_col - 1; | 556 | int col = std::max(0, oldCol - 1); |
543 | auto it = begin; | 557 | auto it = begin; |
544 | for (int i = 0; i < oldCol; ++i) { | 558 | for (int i = 0; i < oldCol; ++i) { |
545 | if (*it > ASCII) { | 559 | if (*it > ASCII) { |
@@ -558,7 +572,7 @@ private: | |||
558 | auto x = statement; | 572 | auto x = statement; |
559 | if (statement->appendix) { | 573 | if (statement->appendix) { |
560 | if (auto assignment = assignmentFrom(statement)) { | 574 | if (auto assignment = assignmentFrom(statement)) { |
561 | auto preDefine = getPredefine(transformAssignDefs(assignment->expList)); | 575 | auto preDefine = getPredefine(assignment); |
562 | if (!preDefine.empty()) out.push_back(preDefine + nll(statement)); | 576 | if (!preDefine.empty()) out.push_back(preDefine + nll(statement)); |
563 | } | 577 | } |
564 | auto appendix = statement->appendix.get(); | 578 | auto appendix = statement->appendix.get(); |
@@ -790,7 +804,7 @@ private: | |||
790 | } | 804 | } |
791 | 805 | ||
792 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { | 806 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { |
793 | auto info = extractDestructureInfo(assignment); | 807 | auto info = extractDestructureInfo(assignment, true); |
794 | if (!info.first.empty()) { | 808 | if (!info.first.empty()) { |
795 | for (const auto& destruct : info.first) { | 809 | for (const auto& destruct : info.first) { |
796 | str_list defs; | 810 | str_list defs; |
@@ -909,11 +923,10 @@ private: | |||
909 | } | 923 | } |
910 | case "With"_id: { | 924 | case "With"_id: { |
911 | auto withNode = static_cast<With_t*>(value); | 925 | auto withNode = static_cast<With_t*>(value); |
912 | str_list temp; | ||
913 | auto expList = assignment->expList.get(); | 926 | auto expList = assignment->expList.get(); |
914 | std::string preDefine = getPredefine(assignment); | 927 | std::string preDefine = getPredefine(assignment); |
915 | transformWith(withNode, temp, expList); | 928 | transformWith(withNode, out, expList); |
916 | out.push_back(preDefine + temp.back()); | 929 | out.back() = preDefine + out.back(); |
917 | return; | 930 | return; |
918 | } | 931 | } |
919 | case "Do"_id: { | 932 | case "Do"_id: { |
@@ -940,50 +953,42 @@ private: | |||
940 | return; | 953 | return; |
941 | } | 954 | } |
942 | case "For"_id: { | 955 | case "For"_id: { |
943 | str_list temp; | ||
944 | auto expList = assignment->expList.get(); | 956 | auto expList = assignment->expList.get(); |
945 | std::string preDefine = getPredefine(assignment); | 957 | std::string preDefine = getPredefine(assignment); |
946 | transformForInPlace(static_cast<For_t*>(value), temp, expList); | 958 | transformForInPlace(static_cast<For_t*>(value), out, expList); |
947 | out.push_back(preDefine + temp.back()); | 959 | out.back() = preDefine + out.back(); |
948 | return; | 960 | return; |
949 | } | 961 | } |
950 | case "ForEach"_id: { | 962 | case "ForEach"_id: { |
951 | str_list temp; | ||
952 | auto expList = assignment->expList.get(); | 963 | auto expList = assignment->expList.get(); |
953 | std::string preDefine = getPredefine(assignment); | 964 | std::string preDefine = getPredefine(assignment); |
954 | transformForEachInPlace(static_cast<ForEach_t*>(value), temp, expList); | 965 | transformForEachInPlace(static_cast<ForEach_t*>(value), out, expList); |
955 | out.push_back(preDefine + temp.back()); | 966 | out.back() = preDefine + out.back(); |
956 | return; | 967 | return; |
957 | } | 968 | } |
958 | case "ClassDecl"_id: { | 969 | case "ClassDecl"_id: { |
959 | str_list temp; | ||
960 | auto expList = assignment->expList.get(); | 970 | auto expList = assignment->expList.get(); |
961 | std::string preDefine = getPredefine(assignment); | 971 | std::string preDefine = getPredefine(assignment); |
962 | transformClassDecl(static_cast<ClassDecl_t*>(value), temp, ExpUsage::Assignment, expList); | 972 | transformClassDecl(static_cast<ClassDecl_t*>(value), out, ExpUsage::Assignment, expList); |
963 | out.push_back(preDefine + temp.back()); | 973 | out.back() = preDefine + out.back(); |
964 | return; | 974 | return; |
965 | } | 975 | } |
966 | case "While"_id: { | 976 | case "While"_id: { |
967 | str_list temp; | ||
968 | auto expList = assignment->expList.get(); | 977 | auto expList = assignment->expList.get(); |
969 | std::string preDefine = getPredefine(assignment); | 978 | std::string preDefine = getPredefine(assignment); |
970 | transformWhileInPlace(static_cast<While_t*>(value), temp, expList); | 979 | transformWhileInPlace(static_cast<While_t*>(value), out, expList); |
971 | out.push_back(preDefine + temp.back()); | 980 | out.back() = preDefine + out.back(); |
972 | return; | 981 | return; |
973 | } | 982 | } |
974 | } | 983 | } |
975 | auto exp = ast_cast<Exp_t>(value); | 984 | auto exp = ast_cast<Exp_t>(value); |
976 | BREAK_IF(!exp); | 985 | BREAK_IF(!exp); |
977 | if (auto chainValue = exp->value->item.as<ChainValue_t>()) { | 986 | if (auto chainValue = exp->value->item.as<ChainValue_t>()) { |
978 | if (isColonChain(chainValue)) { | 987 | if (isSpecialChainValue(chainValue)) { |
979 | auto assignable = assignment->expList.get(); | 988 | auto expList = assignment->expList.get(); |
980 | std::string preDefine = getPredefine(transformAssignDefs(assignable)); | 989 | std::string preDefine = getPredefine(assignment); |
981 | transformColonChain(chainValue, out, ExpUsage::Assignment, assignable); | 990 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList); |
982 | auto nl = preDefine.empty() ? Empty : nll(chainValue); | 991 | out.back() = preDefine + out.back(); |
983 | if (!preDefine.empty()) out.back() = preDefine + nl + out.back(); | ||
984 | return; | ||
985 | } else if (hasKeywordColonChainItem(chainValue)) { | ||
986 | transformChainValue(chainValue, out, ExpUsage::Assignment, assignment->expList); | ||
987 | return; | 992 | return; |
988 | } | 993 | } |
989 | } | 994 | } |
@@ -1169,7 +1174,7 @@ private: | |||
1169 | } | 1174 | } |
1170 | 1175 | ||
1171 | std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> | 1176 | std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> |
1172 | extractDestructureInfo(ExpListAssign_t* assignment) { | 1177 | extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly = false) { |
1173 | auto x = assignment; | 1178 | auto x = assignment; |
1174 | std::list<Destructure> destructs; | 1179 | std::list<Destructure> destructs; |
1175 | if (!assignment->action.is<Assign_t>()) return { destructs, nullptr }; | 1180 | if (!assignment->action.is<Assign_t>()) return { destructs, nullptr }; |
@@ -1187,19 +1192,21 @@ private: | |||
1187 | while (values.size() < size) values.emplace_back(nullNode); | 1192 | while (values.size() < size) values.emplace_back(nullNode); |
1188 | } | 1193 | } |
1189 | using iter = node_container::iterator; | 1194 | using iter = node_container::iterator; |
1190 | std::vector<std::pair<iter, iter>> destructPairs; | 1195 | std::vector<std::pair<iter,iter>> destructPairs; |
1191 | str_list temp; | 1196 | str_list temp; |
1192 | for (auto i = exprs.begin(), j = values.begin(); i != exprs.end(); ++i, ++j) { | 1197 | for (auto i = exprs.begin(), j = values.begin(); i != exprs.end(); ++i, ++j) { |
1193 | auto expr = *i; | 1198 | auto expr = *i; |
1194 | ast_node* destructNode = expr->getByPath<Value_t, SimpleValue_t, TableLit_t>(); | 1199 | ast_node* destructNode = expr->getByPath<Value_t, SimpleValue_t, TableLit_t>(); |
1195 | if (destructNode || (destructNode = expr->getByPath<Value_t, simple_table_t>())) { | 1200 | if (destructNode || (destructNode = expr->getByPath<Value_t, simple_table_t>())) { |
1196 | destructPairs.push_back({i,j}); | 1201 | destructPairs.push_back({i,j}); |
1197 | pushScope(); | ||
1198 | transformAssignItem(*j, temp); | ||
1199 | popScope(); | ||
1200 | auto& destruct = destructs.emplace_back(); | 1202 | auto& destruct = destructs.emplace_back(); |
1201 | destruct.value = temp.back(); | 1203 | if (!varDefOnly) { |
1202 | temp.pop_back(); | 1204 | pushScope(); |
1205 | transformAssignItem(*j, temp); | ||
1206 | destruct.value = temp.back(); | ||
1207 | temp.pop_back(); | ||
1208 | popScope(); | ||
1209 | } | ||
1203 | auto pairs = destructFromExp(expr); | 1210 | auto pairs = destructFromExp(expr); |
1204 | destruct.items = std::move(pairs); | 1211 | destruct.items = std::move(pairs); |
1205 | } | 1212 | } |
@@ -1244,7 +1251,7 @@ private: | |||
1244 | BREAK_IF(!exp); | 1251 | BREAK_IF(!exp); |
1245 | auto var = singleVariableFrom(exp); | 1252 | auto var = singleVariableFrom(exp); |
1246 | BREAK_IF(!var.empty()); | 1253 | BREAK_IF(!var.empty()); |
1247 | auto upVar = getUnusedName("_update_"); | 1254 | auto upVar = getUnusedName("_update_"sv); |
1248 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 1255 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
1249 | assignment->expList.set(toAst<ExpList_t>(upVar, ExpList, x)); | 1256 | assignment->expList.set(toAst<ExpList_t>(upVar, ExpList, x)); |
1250 | auto assign = x->new_ptr<Assign_t>(); | 1257 | auto assign = x->new_ptr<Assign_t>(); |
@@ -1532,11 +1539,7 @@ private: | |||
1532 | case "simple_table"_id: transform_simple_table(static_cast<simple_table_t*>(item), out); break; | 1539 | case "simple_table"_id: transform_simple_table(static_cast<simple_table_t*>(item), out); break; |
1533 | case "ChainValue"_id: { | 1540 | case "ChainValue"_id: { |
1534 | auto chainValue = static_cast<ChainValue_t*>(item); | 1541 | auto chainValue = static_cast<ChainValue_t*>(item); |
1535 | if (isColonChain(chainValue)) { | 1542 | transformChainValue(chainValue, out); |
1536 | transformColonChainClosure(chainValue, out); | ||
1537 | } else { | ||
1538 | transformChainValue(chainValue, out); | ||
1539 | } | ||
1540 | break; | 1543 | break; |
1541 | } | 1544 | } |
1542 | case "String"_id: transformString(static_cast<String_t*>(item), out); break; | 1545 | case "String"_id: transformString(static_cast<String_t*>(item), out); break; |
@@ -1689,7 +1692,7 @@ private: | |||
1689 | any->decls.push_back(var); | 1692 | any->decls.push_back(var); |
1690 | } | 1693 | } |
1691 | } | 1694 | } |
1692 | auto info = extractDestructureInfo(assignment); | 1695 | auto info = extractDestructureInfo(assignment, true); |
1693 | if (!info.first.empty()) { | 1696 | if (!info.first.empty()) { |
1694 | for (const auto& destruct : info.first) | 1697 | for (const auto& destruct : info.first) |
1695 | for (const auto& item : destruct.items) | 1698 | for (const auto& item : destruct.items) |
@@ -1803,12 +1806,10 @@ private: | |||
1803 | } | 1806 | } |
1804 | } | 1807 | } |
1805 | if (auto chainValue = singleValue->item.as<ChainValue_t>()) { | 1808 | if (auto chainValue = singleValue->item.as<ChainValue_t>()) { |
1806 | if (isColonChain(chainValue)) { | 1809 | if (isSpecialChainValue(chainValue)) { |
1807 | transformColonChain(chainValue, out, ExpUsage::Return); | ||
1808 | } else { | ||
1809 | transformChainValue(chainValue, out, ExpUsage::Return); | 1810 | transformChainValue(chainValue, out, ExpUsage::Return); |
1811 | return; | ||
1810 | } | 1812 | } |
1811 | return; | ||
1812 | } | 1813 | } |
1813 | transformValue(singleValue, out); | 1814 | transformValue(singleValue, out); |
1814 | out.back() = indent() + s("return "sv) + out.back() + nlr(returnNode); | 1815 | out.back() = indent() + s("return "sv) + out.back() + nlr(returnNode); |
@@ -1980,111 +1981,292 @@ private: | |||
1980 | } | 1981 | } |
1981 | } | 1982 | } |
1982 | 1983 | ||
1983 | void transformColonChainClosure(ChainValue_t* chainValue, str_list& out) { | 1984 | bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t*) { |
1984 | str_list temp; | 1985 | auto x = chainList.front(); |
1985 | temp.push_back(s("(function()"sv) + nll(chainValue)); | 1986 | if (ast_cast<existential_op_t>(chainList.back())) { |
1986 | pushScope(); | 1987 | auto parens = x->new_ptr<Parens_t>(); |
1987 | transformColonChain(chainValue, temp, ExpUsage::Return); | 1988 | { |
1988 | popScope(); | 1989 | auto chainValue = x->new_ptr<ChainValue_t>(); |
1989 | temp.push_back(indent() + s("end)()"sv)); | 1990 | for (auto item : chainList) { |
1990 | out.push_back(join(temp)); | 1991 | chainValue->items.push_back(item); |
1992 | } | ||
1993 | chainValue->items.pop_back(); | ||
1994 | auto value = x->new_ptr<Value_t>(); | ||
1995 | value->item.set(chainValue); | ||
1996 | auto opValue = x->new_ptr<exp_op_value_t>(); | ||
1997 | opValue->op.set(toAst<BinaryOperator_t>("!="sv, BinaryOperator, x)); | ||
1998 | opValue->value.set(toAst<Value_t>("nil"sv, Value, x)); | ||
1999 | auto exp = x->new_ptr<Exp_t>(); | ||
2000 | exp->value.set(value); | ||
2001 | exp->opValues.push_back(opValue); | ||
2002 | parens->expr.set(exp); | ||
2003 | } | ||
2004 | transformParens(parens, out); | ||
2005 | if (usage == ExpUsage::Return) { | ||
2006 | out.back().insert(0, indent() + s("return "sv)); | ||
2007 | out.back().append(nlr(x)); | ||
2008 | } | ||
2009 | return true; | ||
2010 | } | ||
2011 | return false; | ||
1991 | } | 2012 | } |
1992 | 2013 | ||
1993 | void transformColonChain(ChainValue_t* chainValue, str_list& out, ExpUsage usage = ExpUsage::Common, ExpList_t* expList = nullptr) { | 2014 | bool transformChainWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { |
1994 | auto x = chainValue; | 2015 | auto opIt = std::find_if(chainList.begin(), chainList.end(), [](ast_node* node) { return ast_is<existential_op_t>(node); }); |
1995 | const auto& chainList = chainValue->items.objects(); | 2016 | if (opIt != chainList.end()) { |
1996 | auto baseChain = x->new_ptr<ChainValue_t>(); | 2017 | auto x = chainList.front(); |
1997 | switch (chainList.front()->getId()) { | 2018 | str_list temp; |
1998 | case "DotChainItem"_id: | 2019 | if (usage == ExpUsage::Closure) { |
1999 | case "ColonChainItem"_id: | 2020 | temp.push_back(s("(function()"sv) + nll(x)); |
2000 | if (_withVars.empty()) { | 2021 | pushScope(); |
2001 | throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, chainList.front())); | 2022 | } |
2002 | } else { | 2023 | auto partOne = x->new_ptr<ChainValue_t>(); |
2003 | baseChain->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); | 2024 | for (auto it = chainList.begin();it != opIt;++it) { |
2004 | } | 2025 | partOne->items.push_back(*it); |
2026 | } | ||
2027 | BLOCK_START | ||
2028 | auto back = ast_cast<Callable_t>(partOne->items.back()); | ||
2029 | BREAK_IF(!back); | ||
2030 | auto selfName = ast_cast<SelfName_t>(back->item); | ||
2031 | BREAK_IF(!selfName); | ||
2032 | if (auto sname = ast_cast<self_name_t>(selfName->name)) { | ||
2033 | auto colonItem = x->new_ptr<ColonChainItem_t>(); | ||
2034 | colonItem->name.set(sname->name); | ||
2035 | partOne->items.pop_back(); | ||
2036 | partOne->items.push_back(toAst<Callable_t>("@"sv, Callable, x)); | ||
2037 | partOne->items.push_back(colonItem); | ||
2005 | break; | 2038 | break; |
2006 | } | 2039 | } |
2007 | auto end = --chainList.end(); | 2040 | if (auto cname = ast_cast<self_class_name_t>(selfName->name)) { |
2008 | for (auto it = chainList.begin(); it != end; ++it) { | 2041 | auto colonItem = x->new_ptr<ColonChainItem_t>(); |
2009 | baseChain->items.push_back(*it); | 2042 | colonItem->name.set(cname->name); |
2010 | } | 2043 | partOne->items.pop_back(); |
2011 | auto colonChainItem = static_cast<ColonChainItem_t*>(chainList.back()); | 2044 | partOne->items.push_back(toAst<Callable_t>("@@"sv, Callable, x)); |
2012 | auto funcName = toString(colonChainItem->name); | 2045 | partOne->items.push_back(colonItem); |
2013 | if (usage != ExpUsage::Return) pushScope(); | ||
2014 | auto baseVar = getUnusedName("_base_"sv); | ||
2015 | auto fnVar = getUnusedName("_fn_"sv); | ||
2016 | str_list temp; | ||
2017 | { | ||
2018 | auto value = x->new_ptr<Value_t>(); | ||
2019 | value->item.set(baseChain); | ||
2020 | auto exp = x->new_ptr<Exp_t>(); | ||
2021 | exp->value.set(value); | ||
2022 | auto assign = x->new_ptr<Assign_t>(); | ||
2023 | assign->values.push_back(exp); | ||
2024 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
2025 | assignment->expList.set(toAst<ExpList_t>(baseVar, ExpList, x)); | ||
2026 | assignment->action.set(assign); | ||
2027 | transformAssignment(assignment, temp); | ||
2028 | } | ||
2029 | { | ||
2030 | auto assign = x->new_ptr<Assign_t>(); | ||
2031 | assign->values.push_back(toAst<Exp_t>(baseVar + "." + funcName, Exp, x)); | ||
2032 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
2033 | assignment->expList.set(toAst<ExpList_t>(fnVar, ExpList, x)); | ||
2034 | assignment->action.set(assign); | ||
2035 | transformAssignment(assignment, temp); | ||
2036 | } | ||
2037 | auto funLit = toAst<Exp_t>(s("(...)-> "sv) + fnVar + s(" "sv) + baseVar + s(", ..."sv), Exp, x); | ||
2038 | switch (usage) { | ||
2039 | case ExpUsage::Return: | ||
2040 | transformExp(funLit, temp); | ||
2041 | _buf << temp.front(); | ||
2042 | _buf << *(++temp.begin()); | ||
2043 | _buf << indent() << "return " << temp.back() << nll(chainValue); | ||
2044 | break; | 2046 | break; |
2045 | case ExpUsage::Assignment: { | 2047 | } |
2048 | BLOCK_END | ||
2049 | auto objVar = singleVariableFrom(partOne); | ||
2050 | if (objVar.empty()) { | ||
2051 | objVar = getUnusedName("_obj_"sv); | ||
2052 | if (auto colonItem = ast_cast<ColonChainItem_t>(partOne->items.back())) { | ||
2053 | auto chainValue = x->new_ptr<ChainValue_t>(); | ||
2054 | chainValue->items.dup(partOne->items); | ||
2055 | chainValue->items.pop_back(); | ||
2056 | if (chainValue->items.empty()) { | ||
2057 | if (_withVars.empty()) { | ||
2058 | throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, x)); | ||
2059 | } | ||
2060 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); | ||
2061 | } | ||
2062 | auto newObj = singleVariableFrom(chainValue); | ||
2063 | if (!newObj.empty()) { | ||
2064 | objVar = newObj; | ||
2065 | } else { | ||
2066 | auto value = x->new_ptr<Value_t>(); | ||
2067 | value->item.set(chainValue); | ||
2068 | auto exp = x->new_ptr<Exp_t>(); | ||
2069 | exp->value.set(value); | ||
2070 | auto assign = x->new_ptr<Assign_t>(); | ||
2071 | assign->values.push_back(exp); | ||
2072 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
2073 | expListAssign->expList.set(toAst<ExpList_t>(objVar, ExpList, x)); | ||
2074 | expListAssign->action.set(assign); | ||
2075 | transformAssignment(expListAssign, temp); | ||
2076 | } | ||
2077 | auto dotItem = x->new_ptr<DotChainItem_t>(); | ||
2078 | auto name = colonItem->name.get(); | ||
2079 | if (auto keyword = ast_cast<LuaKeyword_t>(name)) { | ||
2080 | name = keyword->name.get(); | ||
2081 | } | ||
2082 | dotItem->name.set(name); | ||
2083 | partOne->items.clear(); | ||
2084 | partOne->items.push_back(toAst<Callable_t>(objVar, Callable, x)); | ||
2085 | partOne->items.push_back(dotItem); | ||
2086 | auto it = opIt; ++it; | ||
2087 | if (it != chainList.end() && ast_is<Invoke_t, InvokeArgs_t>(*it)) { | ||
2088 | |||
2089 | if (auto invoke = ast_cast<Invoke_t>(*it)) { | ||
2090 | invoke->args.push_front(toAst<Exp_t>(objVar, Exp, x)); | ||
2091 | } else { | ||
2092 | auto invokeArgs = static_cast<InvokeArgs_t*>(*it); | ||
2093 | invokeArgs->args.push_front(toAst<Exp_t>(objVar, Exp, x)); | ||
2094 | } | ||
2095 | } | ||
2096 | objVar = getUnusedName("_obj_"sv); | ||
2097 | } | ||
2098 | auto value = x->new_ptr<Value_t>(); | ||
2099 | value->item.set(partOne); | ||
2100 | auto exp = x->new_ptr<Exp_t>(); | ||
2101 | exp->value.set(value); | ||
2102 | auto assign = x->new_ptr<Assign_t>(); | ||
2103 | assign->values.push_back(exp); | ||
2104 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
2105 | expListAssign->expList.set(toAst<ExpList_t>(objVar, ExpList, x)); | ||
2106 | expListAssign->action.set(assign); | ||
2107 | transformAssignment(expListAssign, temp); | ||
2108 | } | ||
2109 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x); | ||
2110 | temp.push_back(clearBuf()); | ||
2111 | pushScope(); | ||
2112 | auto partTwo = x->new_ptr<ChainValue_t>(); | ||
2113 | partTwo->items.push_back(toAst<Callable_t>(objVar, Callable, x)); | ||
2114 | for (auto it = ++opIt;it != chainList.end();++it) { | ||
2115 | partTwo->items.push_back(*it); | ||
2116 | } | ||
2117 | switch (usage) { | ||
2118 | case ExpUsage::Common: | ||
2119 | transformChainValue(partTwo, temp, ExpUsage::Common); | ||
2120 | break; | ||
2121 | case ExpUsage::Assignment: { | ||
2122 | auto value = x->new_ptr<Value_t>(); | ||
2123 | value->item.set(partTwo); | ||
2124 | auto exp = x->new_ptr<Exp_t>(); | ||
2125 | exp->value.set(value); | ||
2126 | auto assign = x->new_ptr<Assign_t>(); | ||
2127 | assign->values.push_back(exp); | ||
2128 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
2129 | assignment->expList.set(assignList); | ||
2130 | assignment->action.set(assign); | ||
2131 | transformAssignment(assignment, temp); | ||
2132 | break; | ||
2133 | } | ||
2134 | case ExpUsage::Return: | ||
2135 | case ExpUsage::Closure: { | ||
2136 | auto value = x->new_ptr<Value_t>(); | ||
2137 | value->item.set(partTwo); | ||
2138 | auto exp = x->new_ptr<Exp_t>(); | ||
2139 | exp->value.set(value); | ||
2140 | auto ret = x->new_ptr<Return_t>(); | ||
2141 | auto expListLow = x->new_ptr<ExpListLow_t>(); | ||
2142 | expListLow->exprs.push_back(exp); | ||
2143 | ret->valueList.set(expListLow); | ||
2144 | transformReturn(ret, temp); | ||
2145 | break; | ||
2146 | } | ||
2147 | } | ||
2148 | popScope(); | ||
2149 | temp.push_back(indent() + s("end"sv) + nlr(x)); | ||
2150 | switch (usage) { | ||
2151 | case ExpUsage::Return: | ||
2152 | temp.push_back(indent() + s("return nil"sv) + nlr(x)); | ||
2153 | break; | ||
2154 | case ExpUsage::Closure: | ||
2155 | temp.push_back(indent() + s("return nil"sv) + nlr(x)); | ||
2156 | popScope(); | ||
2157 | temp.push_back(indent() + s("end)()"sv)); | ||
2158 | break; | ||
2159 | default: | ||
2160 | break; | ||
2161 | } | ||
2162 | out.push_back(join(temp)); | ||
2163 | return true; | ||
2164 | } | ||
2165 | return false; | ||
2166 | } | ||
2167 | |||
2168 | bool transformChainEndWithColonItem(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { | ||
2169 | if (ast_is<ColonChainItem_t>(chainList.back())) { | ||
2170 | auto x = chainList.front(); | ||
2171 | str_list temp; | ||
2172 | switch (usage) { | ||
2173 | case ExpUsage::Assignment: | ||
2174 | temp.push_back(indent() + s("do"sv) + nll(x)); | ||
2175 | pushScope(); | ||
2176 | break; | ||
2177 | case ExpUsage::Closure: | ||
2178 | temp.push_back(s("(function()"sv) + nll(x)); | ||
2179 | pushScope(); | ||
2180 | break; | ||
2181 | default: | ||
2182 | break; | ||
2183 | } | ||
2184 | auto baseChain = x->new_ptr<ChainValue_t>(); | ||
2185 | switch (chainList.front()->getId()) { | ||
2186 | case "DotChainItem"_id: | ||
2187 | case "ColonChainItem"_id: | ||
2188 | if (_withVars.empty()) { | ||
2189 | throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, chainList.front())); | ||
2190 | } else { | ||
2191 | baseChain->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); | ||
2192 | } | ||
2193 | break; | ||
2194 | } | ||
2195 | auto end = --chainList.end(); | ||
2196 | for (auto it = chainList.begin(); it != end; ++it) { | ||
2197 | baseChain->items.push_back(*it); | ||
2198 | } | ||
2199 | auto colonChainItem = static_cast<ColonChainItem_t*>(chainList.back()); | ||
2200 | auto funcName = toString(colonChainItem->name); | ||
2201 | auto baseVar = getUnusedName("_base_"sv); | ||
2202 | auto fnVar = getUnusedName("_fn_"sv); | ||
2203 | { | ||
2204 | auto value = x->new_ptr<Value_t>(); | ||
2205 | value->item.set(baseChain); | ||
2206 | auto exp = x->new_ptr<Exp_t>(); | ||
2207 | exp->value.set(value); | ||
2046 | auto assign = x->new_ptr<Assign_t>(); | 2208 | auto assign = x->new_ptr<Assign_t>(); |
2047 | assign->values.push_back(funLit); | 2209 | assign->values.push_back(exp); |
2048 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 2210 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
2049 | assignment->expList.set(expList); | 2211 | assignment->expList.set(toAst<ExpList_t>(baseVar, ExpList, x)); |
2050 | assignment->action.set(assign); | 2212 | assignment->action.set(assign); |
2051 | transformAssignment(assignment, temp); | 2213 | transformAssignment(assignment, temp); |
2052 | _buf << indent(-1) << "do"sv << nll(chainValue); | ||
2053 | _buf << temp.front(); | ||
2054 | _buf << *(++temp.begin()); | ||
2055 | _buf << temp.back(); | ||
2056 | popScope(); | ||
2057 | _buf << indent() << "end"sv << nll(chainValue); | ||
2058 | break; | ||
2059 | } | 2214 | } |
2060 | case ExpUsage::Common: { | 2215 | { |
2061 | auto assign = x->new_ptr<Assign_t>(); | 2216 | auto assign = x->new_ptr<Assign_t>(); |
2062 | assign->values.push_back(funLit); | 2217 | assign->values.push_back(toAst<Exp_t>(baseVar + "." + funcName, Exp, x)); |
2063 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 2218 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
2064 | assignment->expList.set(toAst<ExpList_t>("_"sv, ExpList, x)); | 2219 | assignment->expList.set(toAst<ExpList_t>(fnVar, ExpList, x)); |
2065 | assignment->action.set(assign); | 2220 | assignment->action.set(assign); |
2066 | transformAssignment(assignment, temp); | 2221 | transformAssignment(assignment, temp); |
2067 | _buf << indent(-1) << "do"sv << nll(chainValue); | ||
2068 | _buf << temp.front(); | ||
2069 | _buf << *(++temp.begin()); | ||
2070 | _buf << temp.back(); | ||
2071 | popScope(); | ||
2072 | _buf << indent() << "end"sv << nll(chainValue); | ||
2073 | break; | ||
2074 | } | 2222 | } |
2075 | default: break; | 2223 | auto funLit = toAst<Exp_t>(s("(...)-> "sv) + fnVar + s(" "sv) + baseVar + s(", ..."sv), Exp, x); |
2224 | switch (usage) { | ||
2225 | case ExpUsage::Closure: | ||
2226 | case ExpUsage::Return: | ||
2227 | transformExp(funLit, temp); | ||
2228 | _buf << temp.front(); | ||
2229 | _buf << *(++temp.begin()); | ||
2230 | _buf << indent() << "return " << temp.back() << nll(x); | ||
2231 | break; | ||
2232 | case ExpUsage::Assignment: { | ||
2233 | auto assign = x->new_ptr<Assign_t>(); | ||
2234 | assign->values.push_back(funLit); | ||
2235 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
2236 | assignment->expList.set(assignList); | ||
2237 | assignment->action.set(assign); | ||
2238 | transformAssignment(assignment, temp); | ||
2239 | break; | ||
2240 | } | ||
2241 | default: | ||
2242 | break; | ||
2243 | } | ||
2244 | switch (usage) { | ||
2245 | case ExpUsage::Assignment: | ||
2246 | popScope(); | ||
2247 | temp.push_back(indent() + s("end"sv) + nlr(x)); | ||
2248 | break; | ||
2249 | case ExpUsage::Closure: | ||
2250 | popScope(); | ||
2251 | temp.push_back(indent() + s("end)()"sv)); | ||
2252 | break; | ||
2253 | default: | ||
2254 | break; | ||
2255 | } | ||
2256 | out.push_back(join(temp)); | ||
2257 | return true; | ||
2076 | } | 2258 | } |
2077 | out.push_back(clearBuf()); | 2259 | return false; |
2078 | } | 2260 | } |
2079 | 2261 | ||
2080 | void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 2262 | void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
2081 | auto x = chainList.front(); | 2263 | auto x = chainList.front(); |
2082 | str_list temp; | 2264 | str_list temp; |
2083 | switch (chainList.front()->getId()) { | 2265 | switch (x->getId()) { |
2084 | case "DotChainItem"_id: | 2266 | case "DotChainItem"_id: |
2085 | case "ColonChainItem"_id: | 2267 | case "ColonChainItem"_id: |
2086 | if (_withVars.empty()) { | 2268 | if (_withVars.empty()) { |
2087 | throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, chainList.front())); | 2269 | throw std::logic_error(debugInfo("Short dot/colon syntax must be called within a with block."sv, x)); |
2088 | } else { | 2270 | } else { |
2089 | temp.push_back(_withVars.top()); | 2271 | temp.push_back(_withVars.top()); |
2090 | } | 2272 | } |
@@ -2101,8 +2283,20 @@ private: | |||
2101 | break; | 2283 | break; |
2102 | case "ColonChainItem"_id: { | 2284 | case "ColonChainItem"_id: { |
2103 | auto colonItem = static_cast<ColonChainItem_t*>(item); | 2285 | auto colonItem = static_cast<ColonChainItem_t*>(item); |
2104 | auto next = it; ++next; | 2286 | auto current = it; |
2287 | auto next = current; ++next; | ||
2105 | auto followItem = next != chainList.end() ? *next : nullptr; | 2288 | auto followItem = next != chainList.end() ? *next : nullptr; |
2289 | if (current != chainList.begin()) { | ||
2290 | --current; | ||
2291 | if (!ast_is<existential_op_t>(*current)) { | ||
2292 | ++current; | ||
2293 | } | ||
2294 | } | ||
2295 | if (ast_is<existential_op_t>(followItem)) { | ||
2296 | ++next; | ||
2297 | followItem = next != chainList.end() ? *next : nullptr; | ||
2298 | --next; | ||
2299 | } | ||
2106 | if (!ast_is<Invoke_t, InvokeArgs_t>(followItem)) { | 2300 | if (!ast_is<Invoke_t, InvokeArgs_t>(followItem)) { |
2107 | throw std::logic_error(debugInfo("Colon chain item must be followed by invoke arguments."sv, colonItem)); | 2301 | throw std::logic_error(debugInfo("Colon chain item must be followed by invoke arguments."sv, colonItem)); |
2108 | } | 2302 | } |
@@ -2117,7 +2311,7 @@ private: | |||
2117 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); | 2311 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), Callable, x)); |
2118 | break; | 2312 | break; |
2119 | } | 2313 | } |
2120 | for (auto i = chainList.begin(); i != it; ++i) { | 2314 | for (auto i = chainList.begin(); i != current; ++i) { |
2121 | chainValue->items.push_back(*i); | 2315 | chainValue->items.push_back(*i); |
2122 | } | 2316 | } |
2123 | auto value = x->new_ptr<Value_t>(); | 2317 | auto value = x->new_ptr<Value_t>(); |
@@ -2141,6 +2335,9 @@ private: | |||
2141 | auto name = toString(colonItem->name); | 2335 | auto name = toString(colonItem->name); |
2142 | auto chainValue = x->new_ptr<ChainValue_t>(); | 2336 | auto chainValue = x->new_ptr<ChainValue_t>(); |
2143 | chainValue->items.push_back(toAst<Callable_t>(callVar, Callable, x)); | 2337 | chainValue->items.push_back(toAst<Callable_t>(callVar, Callable, x)); |
2338 | if (ast_is<existential_op_t>(*current)) { | ||
2339 | chainValue->items.push_back(x->new_ptr<existential_op_t>()); | ||
2340 | } | ||
2144 | chainValue->items.push_back(toAst<Exp_t>(s("\""sv) + name + s("\""sv), Exp, x)); | 2341 | chainValue->items.push_back(toAst<Exp_t>(s("\""sv) + name + s("\""sv), Exp, x)); |
2145 | if (auto invoke = ast_cast<Invoke_t>(followItem)) { | 2342 | if (auto invoke = ast_cast<Invoke_t>(followItem)) { |
2146 | invoke->args.push_front(toAst<Exp_t>(callVar, Exp, x)); | 2343 | invoke->args.push_front(toAst<Exp_t>(callVar, Exp, x)); |
@@ -2148,8 +2345,7 @@ private: | |||
2148 | auto invokeArgs = static_cast<InvokeArgs_t*>(followItem); | 2345 | auto invokeArgs = static_cast<InvokeArgs_t*>(followItem); |
2149 | invokeArgs->args.push_front(toAst<Exp_t>(callVar, Exp, x)); | 2346 | invokeArgs->args.push_front(toAst<Exp_t>(callVar, Exp, x)); |
2150 | } | 2347 | } |
2151 | chainValue->items.push_back(followItem); | 2348 | for (auto i = next; i != chainList.end(); ++i) { |
2152 | for (auto i = ++next; i != chainList.end(); ++i) { | ||
2153 | chainValue->items.push_back(*i); | 2349 | chainValue->items.push_back(*i); |
2154 | } | 2350 | } |
2155 | auto value = x->new_ptr<Value_t>(); | 2351 | auto value = x->new_ptr<Value_t>(); |
@@ -2244,7 +2440,17 @@ private: | |||
2244 | } | 2440 | } |
2245 | 2441 | ||
2246 | void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage = ExpUsage::Closure, ExpList_t* assignList = nullptr) { | 2442 | void transformChainValue(ChainValue_t* chainValue, str_list& out, ExpUsage usage = ExpUsage::Closure, ExpList_t* assignList = nullptr) { |
2247 | transformChainList(chainValue->items.objects(), out, usage, assignList); | 2443 | const auto& chainList = chainValue->items.objects(); |
2444 | if (transformChainEndWithEOP(chainList, out, usage, assignList)) { | ||
2445 | return; | ||
2446 | } | ||
2447 | if (transformChainWithEOP(chainList, out, usage, assignList)) { | ||
2448 | return; | ||
2449 | } | ||
2450 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { | ||
2451 | return; | ||
2452 | } | ||
2453 | transformChainList(chainList, out, usage, assignList); | ||
2248 | } | 2454 | } |
2249 | 2455 | ||
2250 | void transformAssignableChain(AssignableChain_t* chain, str_list& out) { | 2456 | void transformAssignableChain(AssignableChain_t* chain, str_list& out) { |
@@ -2957,7 +3163,7 @@ private: | |||
2957 | if (auto assignment = assignmentFrom(statement)) { | 3163 | if (auto assignment = assignmentFrom(statement)) { |
2958 | auto names = transformAssignDefs(assignment->expList.get()); | 3164 | auto names = transformAssignDefs(assignment->expList.get()); |
2959 | varDefs.insert(varDefs.end(), names.begin(), names.end()); | 3165 | varDefs.insert(varDefs.end(), names.begin(), names.end()); |
2960 | auto info = extractDestructureInfo(assignment); | 3166 | auto info = extractDestructureInfo(assignment, true); |
2961 | if (!info.first.empty()) { | 3167 | if (!info.first.empty()) { |
2962 | for (const auto& destruct : info.first) | 3168 | for (const auto& destruct : info.first) |
2963 | for (const auto& item : destruct.items) | 3169 | for (const auto& item : destruct.items) |
@@ -3342,7 +3548,7 @@ private: | |||
3342 | if (!names.empty()) { | 3548 | if (!names.empty()) { |
3343 | return traversal::Stop; | 3549 | return traversal::Stop; |
3344 | } | 3550 | } |
3345 | auto info = extractDestructureInfo(assignment); | 3551 | auto info = extractDestructureInfo(assignment, true); |
3346 | if (!info.first.empty()) { | 3552 | if (!info.first.empty()) { |
3347 | for (const auto& destruct : info.first) | 3553 | for (const auto& destruct : info.first) |
3348 | for (const auto& item : destruct.items) | 3554 | for (const auto& item : destruct.items) |
diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index 1005463..7cc4129 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp | |||
@@ -289,9 +289,9 @@ extern rule Value; | |||
289 | rule exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> Value; | 289 | rule exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> Value; |
290 | rule Exp = Value >> *exp_op_value; | 290 | rule Exp = Value >> *exp_op_value; |
291 | 291 | ||
292 | extern rule Chain, Callable, InvokeArgs; | 292 | extern rule Chain, Callable, InvokeArgs, existential_op; |
293 | 293 | ||
294 | rule ChainValue = Seperator >> (Chain | Callable) >> -InvokeArgs; | 294 | rule ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -InvokeArgs; |
295 | 295 | ||
296 | extern rule KeyValue, String, SimpleValue; | 296 | extern rule KeyValue, String, SimpleValue; |
297 | 297 | ||
@@ -345,9 +345,10 @@ rule FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym( | |||
345 | 345 | ||
346 | extern rule ChainItems, DotChainItem, ColonChain; | 346 | extern rule ChainItems, DotChainItem, ColonChain; |
347 | 347 | ||
348 | rule chain_call = (Callable | String) >> ChainItems; | 348 | rule existential_op = expr('?'); |
349 | rule chain_call = (Callable | String) >> -existential_op >> ChainItems; | ||
349 | rule chain_item = and_(set(".\\")) >> ChainItems; | 350 | rule chain_item = and_(set(".\\")) >> ChainItems; |
350 | rule chain_dot_chain = DotChainItem >> -ChainItems; | 351 | rule chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems; |
351 | 352 | ||
352 | rule Chain = chain_call | chain_item | | 353 | rule Chain = chain_call | chain_item | |
353 | Space >> (chain_dot_chain | ColonChain); | 354 | Space >> (chain_dot_chain | ColonChain); |
@@ -362,11 +363,11 @@ rule ChainItems = chain_with_colon | ColonChain; | |||
362 | extern rule Invoke, Slice; | 363 | extern rule Invoke, Slice; |
363 | 364 | ||
364 | rule Index = symx('[') >> Exp >> sym(']'); | 365 | rule Index = symx('[') >> Exp >> sym(']'); |
365 | rule ChainItem = Invoke | DotChainItem | Slice | Index; | 366 | rule ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op; |
366 | rule DotChainItem = symx('.') >> Name; | 367 | rule DotChainItem = symx('.') >> Name; |
367 | rule ColonChainItem = symx('\\') >> (LuaKeyword | Name); | 368 | rule ColonChainItem = symx('\\') >> (LuaKeyword | Name); |
368 | rule invoke_chain = Invoke >> -ChainItems; | 369 | rule invoke_chain = Invoke >> -existential_op >> -ChainItems; |
369 | rule ColonChain = ColonChainItem >> -invoke_chain; | 370 | rule ColonChain = ColonChainItem >> -existential_op >> -invoke_chain; |
370 | 371 | ||
371 | rule default_value = true_(); | 372 | rule default_value = true_(); |
372 | rule Slice = | 373 | rule Slice = |
diff --git a/src/moonc.cpp b/src/moonc.cpp index 02d5275..4498bee 100644 --- a/src/moonc.cpp +++ b/src/moonc.cpp | |||
@@ -22,14 +22,13 @@ int main(int narg, const char** args) { | |||
22 | " -p Write output to standard out\n" | 22 | " -p Write output to standard out\n" |
23 | " -b Dump compile time (doesn't write output)\n" | 23 | " -b Dump compile time (doesn't write output)\n" |
24 | " -l Write line numbers from source codes\n" | 24 | " -l Write line numbers from source codes\n" |
25 | " -a Allow expression list not in the end of body block\n" | ||
26 | " -s Use space over tab\n" | ||
27 | " -v Print version\n"; | 25 | " -v Print version\n"; |
28 | if (narg == 0) { | 26 | if (narg == 0) { |
29 | std::cout << help; | 27 | std::cout << help; |
30 | return 0; | 28 | return 0; |
31 | } | 29 | } |
32 | MoonP::MoonConfig config; | 30 | MoonP::MoonConfig config; |
31 | config.reserveLineNumber = false; | ||
33 | bool writeToFile = true; | 32 | bool writeToFile = true; |
34 | bool dumpCompileTime = false; | 33 | bool dumpCompileTime = false; |
35 | std::string targetPath; | 34 | std::string targetPath; |
@@ -37,18 +36,9 @@ int main(int narg, const char** args) { | |||
37 | std::list<std::string> files; | 36 | std::list<std::string> files; |
38 | for (int i = 1; i < narg; ++i) { | 37 | for (int i = 1; i < narg; ++i) { |
39 | switch (hash(args[i])) { | 38 | switch (hash(args[i])) { |
40 | case "-a"_id: | ||
41 | config.allowExprNotInTheEndOfBody = true; | ||
42 | break; | ||
43 | case "-s"_id: | ||
44 | config.spaceOverTab = true; | ||
45 | break; | ||
46 | case "-l"_id: | 39 | case "-l"_id: |
47 | config.reserveLineNumber = true; | 40 | config.reserveLineNumber = true; |
48 | break; | 41 | break; |
49 | case "-r"_id: | ||
50 | config.reuseVariable = true; | ||
51 | break; | ||
52 | case "-p"_id: | 42 | case "-p"_id: |
53 | writeToFile = false; | 43 | writeToFile = false; |
54 | break; | 44 | break; |