diff options
| author | Li Jin <dragon-fly@qq.com> | 2020-05-26 16:12:44 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2020-05-26 16:12:44 +0800 |
| commit | 04e3cd43cee426cd5c2fa1d0fab5fabc7f19c039 (patch) | |
| tree | dcbf5ce830f5c59a32d4bca9e3df08ac891e14b8 /src | |
| parent | e183579847e5c49b3062e0e5acd3ca320fc1229b (diff) | |
| download | yuescript-04e3cd43cee426cd5c2fa1d0fab5fabc7f19c039.tar.gz yuescript-04e3cd43cee426cd5c2fa1d0fab5fabc7f19c039.tar.bz2 yuescript-04e3cd43cee426cd5c2fa1d0fab5fabc7f19c039.zip | |
make back call operator use highest priority for operator precedence.
Diffstat (limited to '')
| -rw-r--r-- | src/MoonP/moon_compiler.cpp | 169 |
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 | ||
| 45 | const std::string_view version() { | 45 | const 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; |
