Patch 8.2.3716
Problem:    Vim9: range without a command is not compiled.
Solution:   Add the ISN_EXECRANGE byte code.
Files:      src/ex_docmd.c, src/proto/ex_docmd.pro, src/vim9compile.c,
            src/vim9execute.c, src/vim9.h,
            src/testdir/test_vim9_disassemble.vim


*** ../vim-8.2.3715/src/ex_docmd.c      2021-11-29 20:39:06.674101624 +0000
--- src/ex_docmd.c      2021-12-01 14:50:35.384211034 +0000
***************
*** 1977,2019 ****
         */
        if (ea.skip)        // skip this if inside :if
            goto doend;
!       if ((*ea.cmd == '|' || (exmode_active && ea.line1 != ea.line2))
! #ifdef FEAT_EVAL
!               && !vim9script
! #endif
!          )
!       {
!           ea.cmdidx = CMD_print;
!           ea.argt = EX_RANGE+EX_COUNT+EX_TRLBAR;
!           if ((errormsg = invalid_range(&ea)) == NULL)
!           {
!               correct_range(&ea);
!               ex_print(&ea);
!           }
!       }
!       else if (ea.addr_count != 0)
!       {
!           if (ea.line2 > curbuf->b_ml.ml_line_count)
!           {
!               // With '-' in 'cpoptions' a line number past the file is an
!               // error, otherwise put it at the end of the file.
!               if (vim_strchr(p_cpo, CPO_MINUS) != NULL)
!                   ea.line2 = -1;
!               else
!                   ea.line2 = curbuf->b_ml.ml_line_count;
!           }
! 
!           if (ea.line2 < 0)
!               errormsg = _(e_invalid_range);
!           else
!           {
!               if (ea.line2 == 0)
!                   curwin->w_cursor.lnum = 1;
!               else
!                   curwin->w_cursor.lnum = ea.line2;
!               beginline(BL_SOL | BL_FIX);
!           }
!       }
        goto doend;
      }
  
--- 1977,1983 ----
         */
        if (ea.skip)        // skip this if inside :if
            goto doend;
!       errormsg = ex_range_without_command(&ea);
        goto doend;
      }
  
***************
*** 2708,2713 ****
--- 2672,2726 ----
  }
  
  /*
+  * Handle a range without a command.
+  * Returns an error message on failure.
+  */
+     char *
+ ex_range_without_command(exarg_T *eap)
+ {
+     char *errormsg = NULL;
+ 
+     if ((*eap->cmd == '|' || (exmode_active && eap->line1 != eap->line2))
+ #ifdef FEAT_EVAL
+           && !in_vim9script()
+ #endif
+        )
+     {
+       eap->cmdidx = CMD_print;
+       eap->argt = EX_RANGE+EX_COUNT+EX_TRLBAR;
+       if ((errormsg = invalid_range(eap)) == NULL)
+       {
+           correct_range(eap);
+           ex_print(eap);
+       }
+     }
+     else if (eap->addr_count != 0)
+     {
+       if (eap->line2 > curbuf->b_ml.ml_line_count)
+       {
+           // With '-' in 'cpoptions' a line number past the file is an
+           // error, otherwise put it at the end of the file.
+           if (vim_strchr(p_cpo, CPO_MINUS) != NULL)
+               eap->line2 = -1;
+           else
+               eap->line2 = curbuf->b_ml.ml_line_count;
+       }
+ 
+       if (eap->line2 < 0)
+           errormsg = _(e_invalid_range);
+       else
+       {
+           if (eap->line2 == 0)
+               curwin->w_cursor.lnum = 1;
+           else
+               curwin->w_cursor.lnum = eap->line2;
+           beginline(BL_SOL | BL_FIX);
+       }
+     }
+     return errormsg;
+ }
+ 
+ /*
   * Check for an Ex command with optional tail.
   * If there is a match advance "pp" to the argument and return TRUE.
   * If "noparen" is TRUE do not recognize the command followed by "(".
*** ../vim-8.2.3715/src/proto/ex_docmd.pro      2021-08-10 18:52:57.474235537 
+0100
--- src/proto/ex_docmd.pro      2021-12-01 14:50:06.320314008 +0000
***************
*** 7,12 ****
--- 7,13 ----
  void *getline_cookie(char_u *(*fgetline)(int, void *, int, getline_opt_T), 
void *cookie);
  char_u *getline_peek(char_u *(*fgetline)(int, void *, int, getline_opt_T), 
void *cookie);
  char *ex_errmsg(char *msg, char_u *arg);
+ char *ex_range_without_command(exarg_T *eap);
  int checkforcmd(char_u **pp, char *cmd, int len);
  int checkforcmd_noparen(char_u **pp, char *cmd, int len);
  int parse_command_modifiers(exarg_T *eap, char **errormsg, cmdmod_T *cmod, 
int skip_only);
***************
*** 22,28 ****
  void f_fullcommand(typval_T *argvars, typval_T *rettv);
  cmdidx_T excmd_get_cmdidx(char_u *cmd, int len);
  long excmd_get_argt(cmdidx_T idx);
! char_u *skip_range(char_u *cmd, int skip_star, int *ctx);
  void ex_ni(exarg_T *eap);
  int expand_filename(exarg_T *eap, char_u **cmdlinep, char **errormsgp);
  void separate_nextcmd(exarg_T *eap);
--- 23,29 ----
  void f_fullcommand(typval_T *argvars, typval_T *rettv);
  cmdidx_T excmd_get_cmdidx(char_u *cmd, int len);
  long excmd_get_argt(cmdidx_T idx);
! char_u *skip_range(char_u *cmd_start, int skip_star, int *ctx);
  void ex_ni(exarg_T *eap);
  int expand_filename(exarg_T *eap, char_u **cmdlinep, char **errormsgp);
  void separate_nextcmd(exarg_T *eap);
*** ../vim-8.2.3715/src/vim9compile.c   2021-12-01 10:09:12.404191464 +0000
--- src/vim9compile.c   2021-12-01 15:08:01.185162896 +0000
***************
*** 2275,2282 ****
      return OK;
  }
  
      static int
! generate_EXEC(cctx_T *cctx, isntype_T isntype, char_u *line)
  {
      isn_T     *isn;
  
--- 2275,2286 ----
      return OK;
  }
  
+ /*
+  * Generate an EXEC instruction that takes a string argument.
+  * A copy is made of "line".
+  */
      static int
! generate_EXEC_copy(cctx_T *cctx, isntype_T isntype, char_u *line)
  {
      isn_T     *isn;
  
***************
*** 2287,2292 ****
--- 2291,2319 ----
      return OK;
  }
  
+ /*
+  * Generate an EXEC instruction that takes a string argument.
+  * "str" must be allocated, it is consumed.
+  */
+     static int
+ generate_EXEC(cctx_T *cctx, isntype_T isntype, char_u *str)
+ {
+     isn_T     *isn;
+ 
+     if (cctx->ctx_skip == SKIP_YES)
+     {
+       vim_free(str);
+       return OK;
+     }
+     if ((isn = generate_instr(cctx, isntype)) == NULL)
+     {
+       vim_free(str);
+       return FAIL;
+     }
+     isn->isn_arg.string = str;
+     return OK;
+ }
+ 
      static int
  generate_LEGACY_EVAL(cctx_T *cctx, char_u *line)
  {
***************
*** 7552,7558 ****
        vim_snprintf((char *)buf, len, "%s %s",
                eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar",
                p);
!       ret = generate_EXEC(cctx, isn, buf);
  
        vim_free(buf);
        *name_end = cc;
--- 7579,7585 ----
        vim_snprintf((char *)buf, len, "%s %s",
                eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar",
                p);
!       ret = generate_EXEC_copy(cctx, isn, buf);
  
        vim_free(buf);
        *name_end = cc;
***************
*** 9248,9254 ****
        generate_EXECCONCAT(cctx, count);
      }
      else
!       generate_EXEC(cctx, ISN_EXEC, line);
  
  theend:
      if (*nextcmd != NUL)
--- 9275,9281 ----
        generate_EXECCONCAT(cctx, count);
      }
      else
!       generate_EXEC_copy(cctx, ISN_EXEC, line);
  
  theend:
      if (*nextcmd != NUL)
***************
*** 9874,9883 ****
                if (ends_excmd2(line, ea.cmd))
                {
                    // A range without a command: jump to the line.
!                   // TODO: compile to a more efficient command, possibly
!                   // calling parse_cmd_address().
!                   ea.cmdidx = CMD_SIZE;
!                   line = compile_exec(line, &ea, &cctx);
                    goto nextline;
                }
            }
--- 9901,9912 ----
                if (ends_excmd2(line, ea.cmd))
                {
                    // A range without a command: jump to the line.
!                   line = skipwhite(line);
!                   while (*line == ':')
!                       ++line;
!                   generate_EXEC(&cctx, ISN_EXECRANGE,
!                                           vim_strnsave(line, ea.cmd - line));
!                   line = ea.cmd;
                    goto nextline;
                }
            }
***************
*** 10350,10355 ****
--- 10379,10385 ----
      {
        case ISN_DEF:
        case ISN_EXEC:
+       case ISN_EXECRANGE:
        case ISN_EXEC_SPLIT:
        case ISN_LEGACY_EVAL:
        case ISN_LOADAUTO:
*** ../vim-8.2.3715/src/vim9execute.c   2021-11-29 10:36:15.916827518 +0000
--- src/vim9execute.c   2021-12-01 14:58:01.438798689 +0000
***************
*** 1774,1779 ****
--- 1774,1801 ----
                }
                break;
  
+           // execute Ex command line that is only a range
+           case ISN_EXECRANGE:
+               {
+                   exarg_T     ea;
+                   char        *error = NULL;
+ 
+                   CLEAR_FIELD(ea);
+                   ea.cmdidx = CMD_SIZE;
+                   ea.addr_type = ADDR_LINES;
+                   ea.cmd = iptr->isn_arg.string;
+                   parse_cmd_address(&ea, &error, FALSE);
+                   if (error == NULL)
+                       error = ex_range_without_command(&ea);
+                   if (error != NULL)
+                   {
+                       SOURCING_LNUM = iptr->isn_lnum;
+                       emsg(error);
+                       goto on_error;
+                   }
+               }
+               break;
+ 
            // Evaluate an expression with legacy syntax, push it onto the
            // stack.
            case ISN_LEGACY_EVAL:
***************
*** 5068,5073 ****
--- 5090,5098 ----
            case ISN_EXEC_SPLIT:
                smsg("%s%4d EXEC_SPLIT %s", pfx, current, iptr->isn_arg.string);
                break;
+           case ISN_EXECRANGE:
+               smsg("%s%4d EXECRANGE %s", pfx, current, iptr->isn_arg.string);
+               break;
            case ISN_LEGACY_EVAL:
                smsg("%s%4d EVAL legacy %s", pfx, current,
                                                         iptr->isn_arg.string);
*** ../vim-8.2.3715/src/vim9.h  2021-11-28 22:00:08.148081412 +0000
--- src/vim9.h  2021-12-01 14:37:00.840311433 +0000
***************
*** 15,20 ****
--- 15,21 ----
      ISN_EXEC,     // execute Ex command line isn_arg.string
      ISN_EXECCONCAT, // execute Ex command from isn_arg.number items on stack
      ISN_EXEC_SPLIT, // execute Ex command from isn_arg.string split at NL
+     ISN_EXECRANGE,  // execute EX command that is only a range
      ISN_LEGACY_EVAL, // evaluate expression isn_arg.string with legacy syntax.
      ISN_ECHO,     // :echo with isn_arg.echo.echo_count items on top of stack
      ISN_EXECUTE,    // :execute with isn_arg.number items on top of stack
*** ../vim-8.2.3715/src/testdir/test_vim9_disassemble.vim       2021-11-30 
20:57:34.561305257 +0000
--- src/testdir/test_vim9_disassemble.vim       2021-12-01 15:20:31.675255283 
+0000
***************
*** 1999,2004 ****
--- 1999,2023 ----
          res)
  enddef
  
+ def s:OnlyRange()
+   :$
+   :123
+   :'m
+ enddef
+ 
+ def Test_disassemble_range_only()
+   var res = execute('disass s:OnlyRange')
+   assert_match('\<SNR>\d*_OnlyRange\_s*' ..
+         ':$\_s*' ..
+         '\d EXECRANGE $\_s*' ..
+         ':123\_s*' ..
+         '\d EXECRANGE 123\_s*' ..
+         ':''m\_s*' ..
+         '\d EXECRANGE ''m\_s*' ..
+         '\d\+ RETURN void',
+         res)
+ enddef
+ 
  def s:Echomsg()
    echomsg 'some' 'message'
    echoconsole 'nothing'
*** ../vim-8.2.3715/src/version.c       2021-12-01 12:41:25.079773508 +0000
--- src/version.c       2021-12-01 14:35:56.672820240 +0000
***************
*** 755,756 ****
--- 755,758 ----
  {   /* Add new patch number below this line */
+ /**/
+     3716,
  /**/

-- 
DENNIS: Look,  strange women lying on their backs in ponds handing out
        swords ... that's no basis for a system of government.  Supreme
        executive power derives from a mandate from the masses, not from some
        farcical aquatic ceremony.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// 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/20211201152324.E0A131C025D%40moolenaar.net.

Raspunde prin e-mail lui