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 -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220116210011.194671C038E%40moolenaar.net.

Raspunde prin e-mail lui