• R/O
  • SSH

vim: Commit

Mirror of the Vim source from https://github.com/vim/vim


Commit MetaInfo

Révision6af18c69c59d61ce6bd7bfc0fba5a57d8fce700f (tree)
l'heure2022-01-17 06:00:04
AuteurBram Moolenaar <Bram@vim....>
CommiterBram Moolenaar

Message de Log

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.

Change Summary

Modification

diff -r 10acb2602253 -r 6af18c69c59d src/testdir/test_vim9_expr.vim
--- a/src/testdir/test_vim9_expr.vim Sun Jan 16 20:45:03 2022 +0100
+++ b/src/testdir/test_vim9_expr.vim Sun Jan 16 22:00:04 2022 +0100
@@ -3140,7 +3140,6 @@
31403140 CheckDefAndScriptSuccess(lines)
31413141
31423142 lines =<< trim END
3143- vim9script
31443143 def SetNumber(n: number)
31453144 g:number = n
31463145 enddef
@@ -3166,7 +3165,7 @@
31663165
31673166 unlet g:number
31683167 END
3169- CheckScriptSuccess(lines) # TODO: CheckDefAndScriptSuccess()
3168+ CheckDefAndScriptSuccess(lines)
31703169
31713170 lines =<< trim END
31723171 def RetVoid()
diff -r 10acb2602253 -r 6af18c69c59d src/version.c
--- a/src/version.c Sun Jan 16 20:45:03 2022 +0100
+++ b/src/version.c Sun Jan 16 22:00:04 2022 +0100
@@ -751,6 +751,8 @@
751751 static int included_patches[] =
752752 { /* Add new patch number below this line */
753753 /**/
754+ 4116,
755+/**/
754756 4115,
755757 /**/
756758 4114,
diff -r 10acb2602253 -r 6af18c69c59d src/vim9expr.c
--- a/src/vim9expr.c Sun Jan 16 20:45:03 2022 +0100
+++ b/src/vim9expr.c Sun Jan 16 22:00:04 2022 +0100
@@ -1583,6 +1583,8 @@
15831583 return ret;
15841584 }
15851585
1586+static int compile_expr8(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
1587+
15861588 /*
15871589 * Compile whatever comes after "name" or "name()".
15881590 * Advances "*arg" only when something was recognized.
@@ -1651,13 +1653,15 @@
16511653 }
16521654 else if (*p == '-' && p[1] == '>')
16531655 {
1654- char_u *pstart = p;
1656+ char_u *pstart = p;
1657+ int alt;
1658+ char_u *paren;
16551659
1660+ // something->method()
16561661 if (generate_ppconst(cctx, ppconst) == FAIL)
16571662 return FAIL;
16581663 ppconst->pp_is_const = FALSE;
16591664
1660- // something->method()
16611665 // Apply the '!', '-' and '+' first:
16621666 // -1.0->func() works like (-1.0)->func()
16631667 if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)
@@ -1666,7 +1670,48 @@
16661670 p += 2;
16671671 *arg = skipwhite(p);
16681672 // 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 "("
16691678 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)
16701715 {
16711716 int argcount = 1;
16721717 garray_T *stack = &cctx->ctx_type_stack;
@@ -1676,12 +1721,27 @@
16761721 int expr_isn_end;
16771722 int arg_isn_count;
16781723
1679- // Funcref call: list->(Refs[2])(arg)
1680- // or lambda: list->((arg) => expr)(arg)
1681- //
1682- // Fist compile the function expression.
1683- if (compile_parenthesis(arg, cctx, ppconst) == FAIL)
1684- return FAIL;
1724+ if (alt == 2)
1725+ {
1726+ // Funcref call: list->(Refs[2])(arg)
1727+ // or lambda: list->((arg) => expr)(arg)
1728+ //
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+ }
16851745
16861746 // Remember the next instruction index, where the instructions
16871747 // for arguments are being written.
@@ -1742,27 +1802,7 @@
17421802 if (generate_PCALL(cctx, argcount, p - 2, type, FALSE) == FAIL)
17431803 return FAIL;
17441804 }
1745- else
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- }
1805+
17661806 if (keeping_dict)
17671807 {
17681808 keeping_dict = FALSE;
Afficher sur ancien navigateur de dépôt.