Patch 8.2.0487
Problem:    Vim9: compiling not sufficiently tested.
Solution:   Add more tests.  Fix bug with PCALL.
Files:      src/vim9compile.c, src/vim9execute.c, src/vim9.h,
            src/testdir/test_vim9_script.vim,
            src/testdir/test_vim9_disassemble.vim


*** ../vim-8.2.0486/src/vim9compile.c   2020-03-30 22:51:20.647982632 +0200
--- src/vim9compile.c   2020-03-31 22:14:42.410207941 +0200
***************
*** 1196,1201 ****
--- 1196,1206 ----
      // drop the funcref/partial, get back the return value
      ((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
  
+     // If partial is above the arguments it must be cleared and replaced with
+     // the return value.
+     if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
+       return FAIL;
+ 
      return OK;
  }
  
***************
*** 5200,5206 ****
            p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
                                                         ? ea.cmd + 1 : ea.cmd;
            p = to_name_end(p, TRUE);
!           if ((p > ea.cmd && *p != NUL) || *p == '(')
            {
                int oplen;
                int heredoc;
--- 5205,5211 ----
            p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
                                                         ? ea.cmd + 1 : ea.cmd;
            p = to_name_end(p, TRUE);
!           if (p > ea.cmd && *p != NUL)
            {
                int oplen;
                int heredoc;
***************
*** 5538,5543 ****
--- 5543,5549 ----
        case ISN_OPFLOAT:
        case ISN_OPANY:
        case ISN_PCALL:
+       case ISN_PCALL_END:
        case ISN_PUSHF:
        case ISN_PUSHNR:
        case ISN_PUSHBOOL:
*** ../vim-8.2.0486/src/vim9execute.c   2020-03-29 18:40:08.853652561 +0200
--- src/vim9execute.c   2020-03-31 22:57:21.186038745 +0200
***************
*** 345,351 ****
      static int
  call_partial(typval_T *tv, int argcount, ectx_T *ectx)
  {
!     char_u    *name;
      int               called_emsg_before = called_emsg;
  
      if (tv->v_type == VAR_PARTIAL)
--- 345,351 ----
      static int
  call_partial(typval_T *tv, int argcount, ectx_T *ectx)
  {
!     char_u    *name = NULL;
      int               called_emsg_before = called_emsg;
  
      if (tv->v_type == VAR_PARTIAL)
***************
*** 356,364 ****
            return call_ufunc(pt->pt_func, argcount, ectx, NULL);
        name = pt->pt_name;
      }
!     else
        name = tv->vval.v_string;
!     if (call_by_name(name, argcount, ectx, NULL) == FAIL)
      {
        if (called_emsg == called_emsg_before)
            semsg(_(e_unknownfunc), name);
--- 356,364 ----
            return call_ufunc(pt->pt_func, argcount, ectx, NULL);
        name = pt->pt_name;
      }
!     else if (tv->v_type == VAR_FUNC)
        name = tv->vval.v_string;
!     if (name == NULL || call_by_name(name, argcount, ectx, NULL) == FAIL)
      {
        if (called_emsg == called_emsg_before)
            semsg(_(e_unknownfunc), name);
***************
*** 421,427 ****
      typval_T  *tv;
      int               idx;
      int               ret = FAIL;
-     dfunc_T   *dfunc;
      int               defcount = ufunc->uf_args.ga_len - argc;
  
  // Get pointer to item in the stack.
--- 421,426 ----
***************
*** 467,479 ****
        ++ectx.ec_stack.ga_len;
      }
  
!     // Reserve space for local variables.
!     dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
!     for (idx = 0; idx < dfunc->df_varcount; ++idx)
!       STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
!     ectx.ec_stack.ga_len += dfunc->df_varcount;
  
!     ectx.ec_instr = dfunc->df_instr;
  
      // Decide where to start execution, handles optional arguments.
      init_instr_idx(ufunc, argc, &ectx);
--- 466,482 ----
        ++ectx.ec_stack.ga_len;
      }
  
!     {
!       // Reserve space for local variables.
!       dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
!                                                        + ufunc->uf_dfunc_idx;
! 
!       for (idx = 0; idx < dfunc->df_varcount; ++idx)
!           STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
!       ectx.ec_stack.ga_len += dfunc->df_varcount;
  
!       ectx.ec_instr = dfunc->df_instr;
!     }
  
      // Decide where to start execution, handles optional arguments.
      init_instr_idx(ufunc, argc, &ectx);
***************
*** 1022,1039 ****
                        clear_tv(&partial);
                    if (r == FAIL)
                        goto failed;
- 
-                   if (pfunc->cpf_top)
-                   {
-                       // Get the funcref from the stack, overwrite with the
-                       // return value.
-                       clear_tv(tv);
-                       --ectx.ec_stack.ga_len;
-                       *STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
-                   }
                }
                break;
  
            // call a user defined function or funcref/partial
            case ISN_UCALL:
                {
--- 1025,1042 ----
                        clear_tv(&partial);
                    if (r == FAIL)
                        goto failed;
                }
                break;
  
+           case ISN_PCALL_END:
+               // PCALL finished, arguments have been consumed and replaced by
+               // the return value.  Now clear the funcref from the stack,
+               // and move the return value in its place.
+               --ectx.ec_stack.ga_len;
+               clear_tv(STACK_TV_BOT(-1));
+               *STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
+               break;
+ 
            // call a user defined function or funcref/partial
            case ISN_UCALL:
                {
***************
*** 1078,1083 ****
--- 1081,1087 ----
            case ISN_FUNCREF:
                {
                    partial_T   *pt = NULL;
+                   dfunc_T     *dfunc;
  
                    pt = ALLOC_CLEAR_ONE(partial_T);
                    if (pt == NULL)
***************
*** 2005,2010 ****
--- 2009,2017 ----
                           cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
                }
                break;
+           case ISN_PCALL_END:
+               smsg("%4d PCALL end", current);
+               break;
            case ISN_RETURN:
                smsg("%4d RETURN", current);
                break;
*** ../vim-8.2.0486/src/vim9.h  2020-03-20 18:39:42.981273170 +0100
--- src/vim9.h  2020-03-31 23:06:03.492096623 +0200
***************
*** 57,62 ****
--- 57,63 ----
      ISN_DCALL,            // call def function isn_arg.dfunc
      ISN_UCALL,            // call user function or funcref/partial 
isn_arg.ufunc
      ISN_PCALL,            // call partial, use isn_arg.pfunc
+     ISN_PCALL_END,  // cleanup after ISN_PCALL with cpf_top set
      ISN_RETURN,           // return, result is on top of stack
      ISN_FUNCREF,    // push a function ref to dfunc isn_arg.number
  
***************
*** 256,262 ****
  // Functions defined with :def are stored in this growarray.
  // They are never removed, so that they can be found by index.
  // Deleted functions have the df_deleted flag set.
! garray_T def_functions = {0, 0, sizeof(dfunc_T), 50, NULL};
  #else
  extern garray_T def_functions;
  #endif
--- 257,263 ----
  // Functions defined with :def are stored in this growarray.
  // They are never removed, so that they can be found by index.
  // Deleted functions have the df_deleted flag set.
! garray_T def_functions = {0, 0, sizeof(dfunc_T), 200, NULL};
  #else
  extern garray_T def_functions;
  #endif
*** ../vim-8.2.0486/src/testdir/test_vim9_script.vim    2020-03-30 
22:51:20.647982632 +0200
--- src/testdir/test_vim9_script.vim    2020-03-31 21:20:09.159386006 +0200
***************
*** 260,268 ****
    echo a:arg
  endfunc
  
! def Test_call_wrong_arg_count()
    call CheckDefFailure(['TakesOneArg()'], 'E119:')
    call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
  enddef
  
  " Default arg and varargs
--- 260,269 ----
    echo a:arg
  endfunc
  
! def Test_call_wrong_args()
    call CheckDefFailure(['TakesOneArg()'], 'E119:')
    call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
+   call CheckDefFailure(['bufnr(xxx)'], 'E1001:')
  enddef
  
  " Default arg and varargs
***************
*** 1029,1034 ****
--- 1030,1043 ----
    assert_equal('1_3_', result)
  enddef
  
+ def Test_for_loop_fails()
+   call CheckDefFailure(['for # in range(5)'], 'E690:')
+   call CheckDefFailure(['for i In range(5)'], 'E690:')
+   call CheckDefFailure(['let x = 5', 'for x in range(5)'], 'E1023:')
+   call CheckScriptFailure(['def Func(arg)', 'for arg in range(5)', 'enddef'], 
'E1006:')
+   call CheckDefFailure(['for i in "text"'], 'E1024:')
+ enddef
+ 
  def Test_interrupt_loop()
    let caught = false
    let x = 0
*** ../vim-8.2.0486/src/testdir/test_vim9_disassemble.vim       2020-03-19 
14:52:16.973228215 +0100
--- src/testdir/test_vim9_disassemble.vim       2020-03-31 22:53:33.458923423 
+0200
***************
*** 224,229 ****
--- 224,254 ----
  enddef
  
  
+ def EchoArg(arg: string): string
+   return arg
+ enddef
+ def RefThis(): func
+   return function('EchoArg')
+ enddef
+ def s:ScriptPCall()
+   RefThis()("text")
+ enddef
+ 
+ def Test_disassemble_pcall()
+   let res = execute('disass s:ScriptPCall')
+   assert_match('<SNR>\d\+_ScriptPCall.*'
+         \ .. 'RefThis()("text").*'
+         \ .. '\d DCALL RefThis(argc 0).*'
+         \ .. '\d PUSHS "text".*'
+         \ .. '\d PCALL top (argc 1).*'
+         \ .. '\d PCALL end.*'
+         \ .. '\d DROP.*'
+         \ .. '\d PUSHNR 0.*'
+         \ .. '\d RETURN.*'
+         \, res)
+ enddef
+ 
+ 
  def FuncWithForwardCall(): string
    return DefinedLater("yes")
  enddef
*** ../vim-8.2.0486/src/version.c       2020-03-30 22:51:20.647982632 +0200
--- src/version.c       2020-03-31 23:07:02.831880459 +0200
***************
*** 740,741 ****
--- 740,743 ----
  {   /* Add new patch number below this line */
+ /**/
+     487,
  /**/

-- 
My girlfriend told me I should be more affectionate.
So I got TWO girlfriends.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            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/202003312113.02VLDdNg021765%40masaka.moolenaar.net.

Raspunde prin e-mail lui