Patch 8.2.4116
Problem: Vim9: cannot use a method with a complex expression in a :def
function.
Solution: Implement compiling the expression.
Files: src/vim9expr.c, src/testdir/test_vim9_expr.vim
*** ../vim-8.2.4115/src/vim9expr.c 2022-01-13 21:15:17.241958539 +0000
--- src/vim9expr.c 2022-01-16 20:47:04.130684769 +0000
***************
*** 1583,1588 ****
--- 1583,1590 ----
return ret;
}
+ static int compile_expr8(char_u **arg, cctx_T *cctx, ppconst_T *ppconst);
+
/*
* Compile whatever comes after "name" or "name()".
* Advances "*arg" only when something was recognized.
***************
*** 1651,1663 ****
}
else if (*p == '-' && p[1] == '>')
{
! char_u *pstart = p;
if (generate_ppconst(cctx, ppconst) == FAIL)
return FAIL;
ppconst->pp_is_const = FALSE;
- // something->method()
// Apply the '!', '-' and '+' first:
// -1.0->func() works like (-1.0)->func()
if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)
--- 1653,1667 ----
}
else if (*p == '-' && p[1] == '>')
{
! char_u *pstart = p;
! int alt;
! char_u *paren;
+ // something->method()
if (generate_ppconst(cctx, ppconst) == FAIL)
return FAIL;
ppconst->pp_is_const = FALSE;
// Apply the '!', '-' and '+' first:
// -1.0->func() works like (-1.0)->func()
if (compile_leader(cctx, TRUE, start_leader, end_leader) == FAIL)
***************
*** 1666,1672 ****
--- 1670,1717 ----
p += 2;
*arg = skipwhite(p);
// No line break supported right after "->".
+
+ // Three alternatives handled here:
+ // 1. "base->name(" only a name, use compile_call()
+ // 2. "base->(expr)(" evaluate "expr", then use PCALL
+ // 3. "base->expr(" Same, find the end of "expr" by "("
if (**arg == '(')
+ alt = 2;
+ else
+ {
+ // alternative 1 or 3
+ p = *arg;
+ if (!eval_isnamec1(*p))
+ {
+ semsg(_(e_trailing_characters_str), pstart);
+ return FAIL;
+ }
+ if (ASCII_ISALPHA(*p) && p[1] == ':')
+ p += 2;
+ for ( ; eval_isnamec(*p); ++p)
+ ;
+ if (*p == '(')
+ {
+ // alternative 1
+ alt = 1;
+ if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
+ return FAIL;
+ }
+ else
+ {
+ // Must be alternative 3, find the "(". Only works within
+ // one line.
+ alt = 3;
+ paren = vim_strchr(p, '(');
+ if (paren == NULL)
+ {
+ semsg(_(e_missing_parenthesis_str), *arg);
+ return FAIL;
+ }
+ }
+ }
+
+ if (alt != 1)
{
int argcount = 1;
garray_T *stack = &cctx->ctx_type_stack;
***************
*** 1676,1687 ****
int expr_isn_end;
int arg_isn_count;
! // Funcref call: list->(Refs[2])(arg)
! // or lambda: list->((arg) => expr)(arg)
! //
! // Fist compile the function expression.
! if (compile_parenthesis(arg, cctx, ppconst) == FAIL)
! return FAIL;
// Remember the next instruction index, where the instructions
// for arguments are being written.
--- 1721,1747 ----
int expr_isn_end;
int arg_isn_count;
! if (alt == 2)
! {
! // Funcref call: list->(Refs[2])(arg)
! // or lambda: list->((arg) => expr)(arg)
! //
! // Fist compile the function expression.
! if (compile_parenthesis(arg, cctx, ppconst) == FAIL)
! return FAIL;
! }
! else
! {
! *paren = NUL;
! if (compile_expr8(arg, cctx, ppconst) == FAIL
! || *skipwhite(*arg) != NUL)
! {
! *paren = '(';
! semsg(_(e_invalid_expression_str), pstart);
! return FAIL;
! }
! *paren = '(';
! }
// Remember the next instruction index, where the instructions
// for arguments are being written.
***************
*** 1742,1768 ****
if (generate_PCALL(cctx, argcount, p - 2, type, FALSE) == FAIL)
return FAIL;
}
! else
! {
! // method call: list->method()
! p = *arg;
! if (!eval_isnamec1(*p))
! {
! semsg(_(e_trailing_characters_str), pstart);
! return FAIL;
! }
! if (ASCII_ISALPHA(*p) && p[1] == ':')
! p += 2;
! for ( ; eval_isnamec(*p); ++p)
! ;
! if (*p != '(')
! {
! semsg(_(e_missing_parenthesis_str), *arg);
! return FAIL;
! }
! if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
! return FAIL;
! }
if (keeping_dict)
{
keeping_dict = FALSE;
--- 1802,1808 ----
if (generate_PCALL(cctx, argcount, p - 2, type, FALSE) == FAIL)
return FAIL;
}
!
if (keeping_dict)
{
keeping_dict = FALSE;
*** ../vim-8.2.4115/src/testdir/test_vim9_expr.vim 2022-01-16 19:38:04.218156782 +0000
--- src/testdir/test_vim9_expr.vim 2022-01-16 20:41:17.602768656 +0000
***************
*** 3140,3146 ****
CheckDefAndScriptSuccess(lines)
lines =<< trim END
- vim9script
def SetNumber(n: number)
g:number = n
enddef
--- 3140,3145 ----
***************
*** 3166,3172 ****
unlet g:number
END
! CheckScriptSuccess(lines) # TODO: CheckDefAndScriptSuccess()
lines =<< trim END
def RetVoid()
--- 3165,3171 ----
unlet g:number
END
! CheckDefAndScriptSuccess(lines)
lines =<< trim END
def RetVoid()
*** ../vim-8.2.4115/src/version.c 2022-01-16 19:38:04.222156780 +0000
--- src/version.c 2022-01-16 20:54:32.090476466 +0000
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 4116,
/**/
--
[clop clop]
ARTHUR: Old woman!
DENNIS: Man!
ARTHUR: Man, sorry. What knight lives in that castle over there?
DENNIS: I'm thirty seven.
ARTHUR: What?
DENNIS: I'm thirty seven -- I'm not old!
The Quest for the Holy Grail (Monty Python)
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///