aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/MoonP/moon_compiler.cpp169
1 files changed, 107 insertions, 62 deletions
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp
index 36b6b11..189a428 100644
--- a/src/MoonP/moon_compiler.cpp
+++ b/src/MoonP/moon_compiler.cpp
@@ -43,7 +43,7 @@ inline std::string s(std::string_view sv) {
43} 43}
44 44
45const std::string_view version() { 45const std::string_view version() {
46 return "0.3.13"sv; 46 return "0.3.14"sv;
47} 47}
48 48
49// name of table stored in lua registry 49// name of table stored in lua registry
@@ -1612,79 +1612,123 @@ private:
1612 out.push_back(join(temp, ", "sv)); 1612 out.push_back(join(temp, ", "sv));
1613 } 1613 }
1614 1614
1615 void transformExp(Exp_t* exp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 1615 ast_ptr<false, Exp_t> transformBackcall(Value_t* first, node_container::const_iterator begin, node_container::const_iterator end) {
1616 auto x = exp; 1616 auto arg = first->new_ptr<Exp_t>();
1617 const auto& opValues = exp->opValues.objects(); 1617 arg->value.set(first);
1618 for (auto it = opValues.begin(); it != opValues.end(); ++it) { 1618 for (auto it = begin; it != end; ++it) {
1619 auto opValue = static_cast<exp_op_value_t*>(*it); 1619 auto opValue = static_cast<exp_op_value_t*>(*it);
1620 if (opValue->op.is<BackcallOperator_t>()) { 1620 if (auto chainValue = opValue->value->item.as<ChainValue_t>()) {
1621 if (auto chainValue = opValue->value->item.as<ChainValue_t>()) { 1621 auto newArg = first->new_ptr<Exp_t>();
1622 auto newExp = x->new_ptr<Exp_t>(); 1622 {
1623 { 1623 if (isChainValueCall(chainValue)) {
1624 auto arg = x->new_ptr<Exp_t>(); 1624 auto last = chainValue->items.back();
1625 arg->value.set(exp->value); 1625 _ast_list* args = nullptr;
1626 for (auto i = opValues.begin(); i != it; ++i) { 1626 if (auto invoke = ast_cast<InvokeArgs_t>(last)) {
1627 arg->opValues.push_back(*i); 1627 args = &invoke->args;
1628 } 1628 } else {
1629 auto next = it; ++next; 1629 args = &(ast_to<Invoke_t>(last)->args);
1630 for (auto i = next; i != opValues.end(); ++i) {
1631 newExp->opValues.push_back(*i);
1632 } 1630 }
1633 if (isChainValueCall(chainValue)) { 1631 bool findPlaceHolder = false;
1634 auto last = chainValue->items.back(); 1632 for (auto a : args->objects()) {
1635 _ast_list* args = nullptr; 1633 bool lintGlobal = _config.lintGlobalVariable;
1636 if (auto invoke = ast_cast<InvokeArgs_t>(last)) { 1634 _config.lintGlobalVariable = false;
1637 args = &invoke->args; 1635 auto name = singleVariableFrom(a);
1638 } else { 1636 _config.lintGlobalVariable = lintGlobal;
1639 args = &(ast_to<Invoke_t>(last)->args); 1637 if (name == "_"sv) {
1640 } 1638 if (!findPlaceHolder) {
1641 bool findPlaceHolder = false; 1639 args->swap(a, arg);
1642 for (auto a : args->objects()) { 1640 findPlaceHolder = true;
1643 bool lintGlobal = _config.lintGlobalVariable; 1641 } else {
1644 _config.lintGlobalVariable = false; 1642 throw std::logic_error(_info.errorMessage("backcall placeholder can be used only in one place"sv, a));
1645 auto name = singleVariableFrom(a);
1646 _config.lintGlobalVariable = lintGlobal;
1647 if (name == "_"sv) {
1648 if (!findPlaceHolder) {
1649 args->swap(a, arg);
1650 findPlaceHolder = true;
1651 } else {
1652 throw std::logic_error(_info.errorMessage("backcall placeholder can be used only in one place"sv, a));
1653 }
1654 } 1643 }
1655 } 1644 }
1656 if (!findPlaceHolder) {
1657 args->push_front(arg);
1658 }
1659 } else {
1660 auto invoke = x->new_ptr<Invoke_t>();
1661 invoke->args.push_front(arg);
1662 chainValue->items.push_back(invoke);
1663 } 1645 }
1664 auto value = x->new_ptr<Value_t>(); 1646 if (!findPlaceHolder) {
1665 value->item.set(chainValue); 1647 args->push_front(arg);
1666 newExp->value.set(value);
1667 }
1668 if (newExp->opValues.size() == 0) {
1669 if (usage == ExpUsage::Assignment) {
1670 auto assign = x->new_ptr<Assign_t>();
1671 assign->values.push_back(newExp);
1672 auto assignment = x->new_ptr<ExpListAssign_t>();
1673 assignment->expList.set(assignList);
1674 assignment->action.set(assign);
1675 transformAssignment(assignment, out);
1676 } else {
1677 transformChainValue(chainValue, out, usage);
1678 } 1648 }
1679 } else { 1649 } else {
1680 transformExp(newExp, out, usage, assignList); 1650 auto invoke = first->new_ptr<Invoke_t>();
1651 invoke->args.push_front(arg);
1652 chainValue->items.push_back(invoke);
1653 }
1654 auto value = first->new_ptr<Value_t>();
1655 value->item.set(chainValue);
1656 newArg->value.set(value);
1657 arg.set(newArg);
1658 }
1659 } else {
1660 throw std::logic_error(_info.errorMessage("backcall operator must be followed by chain value"sv, opValue->value));
1661 }
1662 }
1663 return arg;
1664 }
1665
1666 void transformExp(Exp_t* exp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
1667 const auto& opValues = exp->opValues.objects();
1668 for (auto it = opValues.begin(); it != opValues.end(); ++it) {
1669 auto opValue = static_cast<exp_op_value_t*>(*it);
1670 if (opValue->op.is<BackcallOperator_t>()) {
1671 auto end = std::find_if_not(it, opValues.end(), [](ast_node* node) {
1672 return static_cast<exp_op_value_t*>(node)->op.is<BackcallOperator_t>();
1673 });
1674 ast_ptr<false, Exp_t> backcall;
1675 if (it == opValues.begin()) {
1676 auto first = exp->value.get();
1677 backcall = transformBackcall(first, it, end);
1678 for (auto i = end; i != opValues.end(); ++i) {
1679 backcall->opValues.push_back(*i);
1681 } 1680 }
1682 return;
1683 } else { 1681 } else {
1684 throw std::logic_error(_info.errorMessage("backcall operator must be followed by chain value"sv, opValue->value)); 1682 auto prev = it; --prev;
1683 auto first = static_cast<exp_op_value_t*>(*prev)->value.get();
1684 backcall = transformBackcall(first, it, end);
1685 for (auto i = opValues.begin(); i != it; ++i) {
1686 backcall->opValues.push_back(*i);
1687 }
1688 static_cast<exp_op_value_t*>(backcall->opValues.back())->value.set(backcall->value);
1689 backcall->value.set(exp->value);
1690 for (auto i = end; i != opValues.end(); ++i) {
1691 backcall->opValues.push_back(*i);
1692 }
1693 }
1694 auto x = exp;
1695 switch (usage) {
1696 case ExpUsage::Assignment: {
1697 auto assignment = x->new_ptr<ExpListAssign_t>();
1698 auto assign = x->new_ptr<Assign_t>();
1699 assign->values.push_back(backcall);
1700 assignment->action.set(assign);
1701 assignment->expList.set(assignList);
1702 transformAssignment(assignment, out);
1703 return;
1704 }
1705 case ExpUsage::Common: {
1706 if (backcall->opValues.empty() && backcall->value->item.is<ChainValue_t>()) {
1707 transformChainValue(backcall->value->item.to<ChainValue_t>(), out, ExpUsage::Common);
1708 } else {
1709 transformExp(backcall, out, ExpUsage::Closure);
1710 out.back().insert(0, indent());
1711 out.back().append(nlr(x));
1712 }
1713 return;
1714 }
1715 case ExpUsage::Return: {
1716 auto ret = x->new_ptr<Return_t>();
1717 auto expListLow = x->new_ptr<ExpListLow_t>();
1718 expListLow->exprs.push_back(backcall);
1719 ret->valueList.set(expListLow);
1720 transformReturn(ret, out);
1721 return;
1722 }
1723 case ExpUsage::Closure: {
1724 transformExp(backcall, out, ExpUsage::Closure);
1725 return;
1726 }
1727 default: assert(false); return;
1685 } 1728 }
1686 } 1729 }
1687 } 1730 }
1731 assert(usage == ExpUsage::Closure);
1688 str_list temp; 1732 str_list temp;
1689 transformValue(exp->value, temp); 1733 transformValue(exp->value, temp);
1690 for (auto _opValue : exp->opValues.objects()) { 1734 for (auto _opValue : exp->opValues.objects()) {
@@ -2954,6 +2998,7 @@ private:
2954 case ExpUsage::Return: 2998 case ExpUsage::Return:
2955 out.push_back(indent() + s("return "sv) + join(temp) + nll(chainList.front())); 2999 out.push_back(indent() + s("return "sv) + join(temp) + nll(chainList.front()));
2956 break; 3000 break;
3001 case ExpUsage::Assignment: assert(false); break;
2957 default: 3002 default:
2958 out.push_back(join(temp)); 3003 out.push_back(join(temp));
2959 break; 3004 break;