aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2020-01-18 18:15:24 +0800
committerLi Jin <dragon-fly@qq.com>2020-01-18 18:15:24 +0800
commit8d1af508f4173e4af6a4ea98584c1a86619f6a20 (patch)
tree0264c4b01f1152d8114cf46aea6fd773276c0b01 /src
parentf53ccb373efbf6f6f40284111df309e351c2c18f (diff)
downloadyuescript-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.hpp6
-rw-r--r--src/MoonP/moon_ast.cpp1
-rw-r--r--src/MoonP/moon_ast.h5
-rw-r--r--src/MoonP/moon_compiler.cpp508
-rw-r--r--src/MoonP/moon_parser.cpp15
-rw-r--r--src/moonc.cpp12
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)
79AST_IMPL(default_value) 79AST_IMPL(default_value)
80AST_IMPL(Slice) 80AST_IMPL(Slice)
81AST_IMPL(Invoke) 81AST_IMPL(Invoke)
82AST_IMPL(existential_op)
82AST_IMPL(TableLit) 83AST_IMPL(TableLit)
83AST_IMPL(TableBlock) 84AST_IMPL(TableBlock)
84AST_IMPL(class_member_list) 85AST_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)
408AST_END(Invoke) 408AST_END(Invoke)
409 409
410AST_LEAF(existential_op, "existential_op"_id)
411AST_END(existential_op)
412
410class InvokeArgs_t; 413class InvokeArgs_t;
411 414
412AST_NODE(ChainValue, "ChainValue"_id) 415AST_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)
416AST_END(ChainValue) 419AST_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>
18using namespace std::string_view_literals; 19using 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;
289rule exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> Value; 289rule exp_op_value = Space >> BinaryOperator >> *SpaceBreak >> Value;
290rule Exp = Value >> *exp_op_value; 290rule Exp = Value >> *exp_op_value;
291 291
292extern rule Chain, Callable, InvokeArgs; 292extern rule Chain, Callable, InvokeArgs, existential_op;
293 293
294rule ChainValue = Seperator >> (Chain | Callable) >> -InvokeArgs; 294rule ChainValue = Seperator >> (Chain | Callable) >> -existential_op >> -InvokeArgs;
295 295
296extern rule KeyValue, String, SimpleValue; 296extern rule KeyValue, String, SimpleValue;
297 297
@@ -345,9 +345,10 @@ rule FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(
345 345
346extern rule ChainItems, DotChainItem, ColonChain; 346extern rule ChainItems, DotChainItem, ColonChain;
347 347
348rule chain_call = (Callable | String) >> ChainItems; 348rule existential_op = expr('?');
349rule chain_call = (Callable | String) >> -existential_op >> ChainItems;
349rule chain_item = and_(set(".\\")) >> ChainItems; 350rule chain_item = and_(set(".\\")) >> ChainItems;
350rule chain_dot_chain = DotChainItem >> -ChainItems; 351rule chain_dot_chain = DotChainItem >> -existential_op >> -ChainItems;
351 352
352rule Chain = chain_call | chain_item | 353rule 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;
362extern rule Invoke, Slice; 363extern rule Invoke, Slice;
363 364
364rule Index = symx('[') >> Exp >> sym(']'); 365rule Index = symx('[') >> Exp >> sym(']');
365rule ChainItem = Invoke | DotChainItem | Slice | Index; 366rule ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op;
366rule DotChainItem = symx('.') >> Name; 367rule DotChainItem = symx('.') >> Name;
367rule ColonChainItem = symx('\\') >> (LuaKeyword | Name); 368rule ColonChainItem = symx('\\') >> (LuaKeyword | Name);
368rule invoke_chain = Invoke >> -ChainItems; 369rule invoke_chain = Invoke >> -existential_op >> -ChainItems;
369rule ColonChain = ColonChainItem >> -invoke_chain; 370rule ColonChain = ColonChainItem >> -existential_op >> -invoke_chain;
370 371
371rule default_value = true_(); 372rule default_value = true_();
372rule Slice = 373rule 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;