Mercurial > vim
comparison src/vim9expr.c @ 27175:6af18c69c59d v8.2.4116
patch 8.2.4116: Vim9: cannot use a method with a complex expression in :def
Commit: https://github.com/vim/vim/commit/c73499351aef8b611b13c70ef8706a7e98df67a8
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jan 16 20:59:39 2022 +0000
patch 8.2.4116: Vim9: cannot use a method with a complex expression in :def
Problem: Vim9: cannot use a method with a complex expression in a :def
function.
Solution: Implement compiling the expression.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 16 Jan 2022 22:00:04 +0100 |
parents | 98a01021e465 |
children | 63f8dbcf6a74 |
comparison
equal
deleted
inserted
replaced
27174:10acb2602253 | 27175:6af18c69c59d |
---|---|
1581 ret = FAIL; | 1581 ret = FAIL; |
1582 } | 1582 } |
1583 return ret; | 1583 return ret; |
1584 } | 1584 } |
1585 | 1585 |
1586 static int compile_expr8(char_u **arg, cctx_T *cctx, ppconst_T *ppconst); | |
1587 | |
1586 /* | 1588 /* |
1587 * Compile whatever comes after "name" or "name()". | 1589 * Compile whatever comes after "name" or "name()". |
1588 * Advances "*arg" only when something was recognized. | 1590 * Advances "*arg" only when something was recognized. |
1589 */ | 1591 */ |
1590 static int | 1592 static int |
1649 return FAIL; | 1651 return FAIL; |
1650 } | 1652 } |
1651 } | 1653 } |
1652 else if (*p == '-' && p[1] == '>') | 1654 else if (*p == '-' && p[1] == '>') |
1653 { | 1655 { |
1654 char_u *pstart = p; | 1656 char_u *pstart = p; |
1655 | 1657 int alt; |
1658 char_u *paren; | |
1659 | |
1660 // something->method() | |
1656 if (generate_ppconst(cctx, ppconst) == FAIL) | 1661 if (generate_ppconst(cctx, ppconst) == FAIL) |
1657 return FAIL; | 1662 return FAIL; |
1658 ppconst->pp_is_const = FALSE; | 1663 ppconst->pp_is_const = FALSE; |
1659 | 1664 |
1660 // something->method() | |
1661 // Apply the '!', '-' and '+' first: | 1665 // Apply the '!', '-' and '+' first: |
1662 // -1.0->func() works like (-1.0)->func() | 1666 // -1.0->func() works like (-1.0)->func() |
1663 if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL) | 1667 if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL) |
1664 return FAIL; | 1668 return FAIL; |
1665 | 1669 |
1666 p += 2; | 1670 p += 2; |
1667 *arg = skipwhite(p); | 1671 *arg = skipwhite(p); |
1668 // No line break supported right after "->". | 1672 // No line break supported right after "->". |
1673 | |
1674 // Three alternatives handled here: | |
1675 // 1. "base->name(" only a name, use compile_call() | |
1676 // 2. "base->(expr)(" evaluate "expr", then use PCALL | |
1677 // 3. "base->expr(" Same, find the end of "expr" by "(" | |
1669 if (**arg == '(') | 1678 if (**arg == '(') |
1679 alt = 2; | |
1680 else | |
1681 { | |
1682 // alternative 1 or 3 | |
1683 p = *arg; | |
1684 if (!eval_isnamec1(*p)) | |
1685 { | |
1686 semsg(_(e_trailing_characters_str), pstart); | |
1687 return FAIL; | |
1688 } | |
1689 if (ASCII_ISALPHA(*p) && p[1] == ':') | |
1690 p += 2; | |
1691 for ( ; eval_isnamec(*p); ++p) | |
1692 ; | |
1693 if (*p == '(') | |
1694 { | |
1695 // alternative 1 | |
1696 alt = 1; | |
1697 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL) | |
1698 return FAIL; | |
1699 } | |
1700 else | |
1701 { | |
1702 // Must be alternative 3, find the "(". Only works within | |
1703 // one line. | |
1704 alt = 3; | |
1705 paren = vim_strchr(p, '('); | |
1706 if (paren == NULL) | |
1707 { | |
1708 semsg(_(e_missing_parenthesis_str), *arg); | |
1709 return FAIL; | |
1710 } | |
1711 } | |
1712 } | |
1713 | |
1714 if (alt != 1) | |
1670 { | 1715 { |
1671 int argcount = 1; | 1716 int argcount = 1; |
1672 garray_T *stack = &cctx->ctx_type_stack; | 1717 garray_T *stack = &cctx->ctx_type_stack; |
1673 int type_idx_start = stack->ga_len; | 1718 int type_idx_start = stack->ga_len; |
1674 type_T *type; | 1719 type_T *type; |
1675 int expr_isn_start = cctx->ctx_instr.ga_len; | 1720 int expr_isn_start = cctx->ctx_instr.ga_len; |
1676 int expr_isn_end; | 1721 int expr_isn_end; |
1677 int arg_isn_count; | 1722 int arg_isn_count; |
1678 | 1723 |
1679 // Funcref call: list->(Refs[2])(arg) | 1724 if (alt == 2) |
1680 // or lambda: list->((arg) => expr)(arg) | 1725 { |
1681 // | 1726 // Funcref call: list->(Refs[2])(arg) |
1682 // Fist compile the function expression. | 1727 // or lambda: list->((arg) => expr)(arg) |
1683 if (compile_parenthesis(arg, cctx, ppconst) == FAIL) | 1728 // |
1684 return FAIL; | 1729 // Fist compile the function expression. |
1730 if (compile_parenthesis(arg, cctx, ppconst) == FAIL) | |
1731 return FAIL; | |
1732 } | |
1733 else | |
1734 { | |
1735 *paren = NUL; | |
1736 if (compile_expr8(arg, cctx, ppconst) == FAIL | |
1737 || *skipwhite(*arg) != NUL) | |
1738 { | |
1739 *paren = '('; | |
1740 semsg(_(e_invalid_expression_str), pstart); | |
1741 return FAIL; | |
1742 } | |
1743 *paren = '('; | |
1744 } | |
1685 | 1745 |
1686 // Remember the next instruction index, where the instructions | 1746 // Remember the next instruction index, where the instructions |
1687 // for arguments are being written. | 1747 // for arguments are being written. |
1688 expr_isn_end = cctx->ctx_instr.ga_len; | 1748 expr_isn_end = cctx->ctx_instr.ga_len; |
1689 | 1749 |
1740 | 1800 |
1741 type = get_type_on_stack(cctx, 0); | 1801 type = get_type_on_stack(cctx, 0); |
1742 if (generate_PCALL(cctx, argcount, p - 2, type, FALSE) == FAIL) | 1802 if (generate_PCALL(cctx, argcount, p - 2, type, FALSE) == FAIL) |
1743 return FAIL; | 1803 return FAIL; |
1744 } | 1804 } |
1745 else | 1805 |
1746 { | |
1747 // method call: list->method() | |
1748 p = *arg; | |
1749 if (!eval_isnamec1(*p)) | |
1750 { | |
1751 semsg(_(e_trailing_characters_str), pstart); | |
1752 return FAIL; | |
1753 } | |
1754 if (ASCII_ISALPHA(*p) && p[1] == ':') | |
1755 p += 2; | |
1756 for ( ; eval_isnamec(*p); ++p) | |
1757 ; | |
1758 if (*p != '(') | |
1759 { | |
1760 semsg(_(e_missing_parenthesis_str), *arg); | |
1761 return FAIL; | |
1762 } | |
1763 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL) | |
1764 return FAIL; | |
1765 } | |
1766 if (keeping_dict) | 1806 if (keeping_dict) |
1767 { | 1807 { |
1768 keeping_dict = FALSE; | 1808 keeping_dict = FALSE; |
1769 if (generate_instr(cctx, ISN_CLEARDICT) == NULL) | 1809 if (generate_instr(cctx, ISN_CLEARDICT) == NULL) |
1770 return FAIL; | 1810 return FAIL; |