Patch 8.2.2842
Problem:    Vim9: skip argument to searchpair() is not compiled.
Solution:   Add VAR_INSTR.
Files:      src/structs.h, src/vim9.h, src/vim9compile.c, src/vim9execute.c,
            src/proto/vim9execute.pro, src/eval.c, src/evalfunc.c, src/vim.h,
            src/evalvars.c, src/typval.c, src/vim9type.c, src/testing.c,
            src/viminfo.c, src/if_py_both.h, src/json.c,
            src/testdir/test_vim9_disassemble.vim,
            src/testdir/test_vim9_builtin.vim


*** ../vim-8.2.2841/src/structs.h       2021-04-24 14:15:03.680264471 +0200
--- src/structs.h       2021-05-07 15:33:39.708802153 +0200
***************
*** 1371,1376 ****
--- 1371,1377 ----
  typedef struct channel_S channel_T;
  typedef struct cctx_S cctx_T;
  typedef struct ectx_S ectx_T;
+ typedef struct instr_S instr_T;
  
  typedef enum
  {
***************
*** 1389,1394 ****
--- 1390,1396 ----
      VAR_DICT,         // "v_dict" is used
      VAR_JOB,          // "v_job" is used
      VAR_CHANNEL,      // "v_channel" is used
+     VAR_INSTR,                // "v_instr" is used
  } vartype_T;
  
  // A type specification.
***************
*** 1429,1434 ****
--- 1431,1437 ----
        channel_T       *v_channel;     // channel value (can be NULL!)
  #endif
        blob_T          *v_blob;        // blob value (can be NULL!)
+       instr_T         *v_instr;       // instructions to execute
      }         vval;
  } typval_T;
  
*** ../vim-8.2.2841/src/vim9.h  2021-05-05 21:31:36.068018579 +0200
--- src/vim9.h  2021-05-07 16:52:30.209276710 +0200
***************
*** 20,25 ****
--- 20,26 ----
      ISN_ECHOERR,    // echo Ex commands isn_arg.number items on top of stack
      ISN_RANGE,            // compute range from isn_arg.string, push to stack
      ISN_SUBSTITUTE, // :s command with expression
+     ISN_INSTR,            // instructions compiled from expression
  
      // get and set variables
      ISN_LOAD,     // push local variable isn_arg.number
***************
*** 411,416 ****
--- 412,418 ----
        isn_outer_T         outer;
        subs_T              subs;
        cexpr_T             cexpr;
+       isn_T               *instr;
      } isn_arg;
  };
  
*** ../vim-8.2.2841/src/vim9compile.c   2021-05-06 21:04:51.514534033 +0200
--- src/vim9compile.c   2021-05-07 16:54:08.825005973 +0200
***************
*** 615,620 ****
--- 615,621 ----
        case VAR_DICT:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
                         to_string_error((*type)->tt_type);
                         return FAIL;
      }
***************
*** 3097,3112 ****
      return res;
  }
  
  /*
   * Compile the argument expressions.
   * "arg" points to just after the "(" and is advanced to after the ")"
   */
      static int
! compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
  {
      char_u  *p = *arg;
      char_u  *whitep = *arg;
      int           must_end = FALSE;
  
      for (;;)
      {
--- 3098,3169 ----
      return res;
  }
  
+     static void
+ clear_instr_ga(garray_T *gap)
+ {
+     int idx;
+ 
+     for (idx = 0; idx < gap->ga_len; ++idx)
+       delete_instr(((isn_T *)gap->ga_data) + idx);
+     ga_clear(gap);
+ }
+ 
+ /*
+  * Compile a string in a ISN_PUSHS instruction into an ISN_INSTR.
+  * Returns FAIL if compilation fails.
+  */
+     static int
+ compile_string(isn_T *isn, cctx_T *cctx)
+ {
+     char_u    *s = isn->isn_arg.string;
+     garray_T  save_ga = cctx->ctx_instr;
+     int               expr_res;
+     int               trailing_error;
+     int               instr_count;
+     isn_T     *instr = NULL;
+ 
+     // Temporarily reset the list of instructions so that the jump labels are
+     // correct.
+     cctx->ctx_instr.ga_len = 0;
+     cctx->ctx_instr.ga_maxlen = 0;
+     cctx->ctx_instr.ga_data = NULL;
+     expr_res = compile_expr0(&s, cctx);
+     s = skipwhite(s);
+     trailing_error = *s != NUL;
+ 
+     if (expr_res == FAIL || trailing_error)
+     {
+       if (trailing_error)
+           semsg(_(e_trailing_arg), s);
+       clear_instr_ga(&cctx->ctx_instr);
+       cctx->ctx_instr = save_ga;
+       return FAIL;
+     }
+ 
+     // Move the generated instructions into the ISN_INSTR instruction, then
+     // restore the list of instructions.
+     instr_count = cctx->ctx_instr.ga_len;
+     instr = cctx->ctx_instr.ga_data;
+     instr[instr_count].isn_type = ISN_FINISH;
+ 
+     cctx->ctx_instr = save_ga;
+     vim_free(isn->isn_arg.string);
+     isn->isn_type = ISN_INSTR;
+     isn->isn_arg.instr = instr;
+     return OK;
+ }
+ 
  /*
   * Compile the argument expressions.
   * "arg" points to just after the "(" and is advanced to after the ")"
   */
      static int
! compile_arguments(char_u **arg, cctx_T *cctx, int *argcount, int 
is_searchpair)
  {
      char_u  *p = *arg;
      char_u  *whitep = *arg;
      int           must_end = FALSE;
+     int           instr_count;
  
      for (;;)
      {
***************
*** 3123,3132 ****
--- 3180,3200 ----
            return FAIL;
        }
  
+       instr_count = cctx->ctx_instr.ga_len;
        if (compile_expr0(&p, cctx) == FAIL)
            return FAIL;
        ++*argcount;
  
+       if (is_searchpair && *argcount == 5
+               && cctx->ctx_instr.ga_len == instr_count + 1)
+       {
+           isn_T *isn = ((isn_T *)cctx->ctx_instr.ga_data) + instr_count;
+ 
+           // {skip} argument of searchpair() can be compiled if not empty
+           if (isn->isn_type == ISN_PUSHS && *isn->isn_arg.string != NUL)
+               compile_string(isn, cctx);
+       }
+ 
        if (*p != ',' && *skipwhite(p) == ',')
        {
            semsg(_(e_no_white_space_allowed_before_str_str), ",", p);
***************
*** 3175,3180 ****
--- 3243,3249 ----
      ufunc_T   *ufunc = NULL;
      int               res = FAIL;
      int               is_autoload;
+     int               is_searchpair;
  
      // we can evaluate "has('name')" at compile time
      if (varlen == 3 && STRNCMP(*arg, "has", 3) == 0)
***************
*** 3216,3223 ****
      vim_strncpy(namebuf, *arg, varlen);
      name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
  
      *arg = skipwhite(*arg + varlen + 1);
!     if (compile_arguments(arg, cctx, &argcount) == FAIL)
        goto theend;
  
      is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
--- 3285,3295 ----
      vim_strncpy(namebuf, *arg, varlen);
      name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
  
+     // we handle the "skip" argument of searchpair() differently
+     is_searchpair = (varlen == 10 && STRNCMP(*arg, "searchpair", 10) == 0);
+ 
      *arg = skipwhite(*arg + varlen + 1);
!     if (compile_arguments(arg, cctx, &argcount, is_searchpair) == FAIL)
        goto theend;
  
      is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
***************
*** 4027,4033 ****
            type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
  
            *arg = skipwhite(p + 1);
!           if (compile_arguments(arg, cctx, &argcount) == FAIL)
                return FAIL;
            if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
                return FAIL;
--- 4099,4105 ----
            type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
  
            *arg = skipwhite(p + 1);
!           if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL)
                return FAIL;
            if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
                return FAIL;
***************
*** 4080,4086 ****
                    return FAIL;
                }
                *arg = skipwhite(*arg + 1);
!               if (compile_arguments(arg, cctx, &argcount) == FAIL)
                    return FAIL;
  
                // Move the instructions for the arguments to before the
--- 4152,4158 ----
                    return FAIL;
                }
                *arg = skipwhite(*arg + 1);
!               if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL)
                    return FAIL;
  
                // Move the instructions for the arguments to before the
***************
*** 6728,6733 ****
--- 6800,6806 ----
                    case VAR_ANY:
                    case VAR_PARTIAL:
                    case VAR_VOID:
+                   case VAR_INSTR:
                    case VAR_SPECIAL:  // cannot happen
                        generate_PUSHNR(cctx, 0);
                        break;
***************
*** 8536,8551 ****
  }
  
  
-     static void
- clear_instr_ga(garray_T *gap)
- {
-     int idx;
- 
-     for (idx = 0; idx < gap->ga_len; ++idx)
-       delete_instr(((isn_T *)gap->ga_data) + idx);
-     ga_clear(gap);
- }
- 
  /*
   * :s/pat/repl/
   */
--- 8609,8614 ----
***************
*** 8568,8580 ****
            int         expr_res;
            int         trailing_error;
            int         instr_count;
!           isn_T       *instr = NULL;
            isn_T       *isn;
  
            cmd += 3;
            end = skip_substitute(cmd, delimiter);
  
!           // Temporarily reset the list of instructions so that the jumps
            // labels are correct.
            cctx->ctx_instr.ga_len = 0;
            cctx->ctx_instr.ga_maxlen = 0;
--- 8631,8643 ----
            int         expr_res;
            int         trailing_error;
            int         instr_count;
!           isn_T       *instr;
            isn_T       *isn;
  
            cmd += 3;
            end = skip_substitute(cmd, delimiter);
  
!           // Temporarily reset the list of instructions so that the jump
            // labels are correct.
            cctx->ctx_instr.ga_len = 0;
            cctx->ctx_instr.ga_maxlen = 0;
***************
*** 8592,8598 ****
                    semsg(_(e_trailing_arg), cmd);
                clear_instr_ga(&cctx->ctx_instr);
                cctx->ctx_instr = save_ga;
-               vim_free(instr);
                return NULL;
            }
  
--- 8655,8660 ----
***************
*** 9552,9557 ****
--- 9614,9630 ----
                for (idx = 0; list[idx].isn_type != ISN_FINISH; ++idx)
                    delete_instr(list + idx);
                vim_free(list);
+           }
+           break;
+ 
+       case ISN_INSTR:
+           {
+               int     idx;
+               isn_T   *list = isn->isn_arg.instr;
+ 
+               for (idx = 0; list[idx].isn_type != ISN_FINISH; ++idx)
+                   delete_instr(list + idx);
+               vim_free(list);
            }
            break;
  
*** ../vim-8.2.2841/src/vim9execute.c   2021-05-05 22:51:35.631336525 +0200
--- src/vim9execute.c   2021-05-07 16:57:49.448411700 +0200
***************
*** 1259,1264 ****
--- 1259,1270 ----
      return OK;
  }
  
+ // used for v_instr of typval of VAR_INSTR
+ struct instr_S {
+     ectx_T    *instr_ectx;
+     isn_T     *instr_instr;
+ };
+ 
  // used for substitute_instr
  typedef struct subs_expr_S {
      ectx_T    *subs_ectx;
***************
*** 1379,1384 ****
--- 1385,1407 ----
                }
                break;
  
+           // push typeval VAR_INSTR with instructions to be executed
+           case ISN_INSTR:
+               {
+                   if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+                       return FAIL;
+                   tv = STACK_TV_BOT(0);
+                   tv->vval.v_instr = ALLOC_ONE(instr_T);
+                   if (tv->vval.v_instr == NULL)
+                       goto on_error;
+                   ++ectx->ec_stack.ga_len;
+ 
+                   tv->v_type = VAR_INSTR;
+                   tv->vval.v_instr->instr_ectx = ectx;
+                   tv->vval.v_instr->instr_instr = iptr->isn_arg.instr;
+               }
+               break;
+ 
            // execute :substitute with an expression
            case ISN_SUBSTITUTE:
                {
***************
*** 3997,4002 ****
--- 4020,4052 ----
  }
  
  /*
+  * Execute the instructions from a VAR_INSTR typeval and put the result in
+  * "rettv".
+  * Return OK or FAIL.
+  */
+     int
+ exe_typval_instr(typval_T *tv, typval_T *rettv)
+ {
+     ectx_T    *ectx = tv->vval.v_instr->instr_ectx;
+     isn_T     *save_instr = ectx->ec_instr;
+     int               save_iidx = ectx->ec_iidx;
+     int               res;
+ 
+     ectx->ec_instr = tv->vval.v_instr->instr_instr;
+     res = exec_instructions(ectx);
+     if (res == OK)
+     {
+       *rettv = *STACK_TV_BOT(-1);
+       --ectx->ec_stack.ga_len;
+     }
+ 
+     ectx->ec_instr = save_instr;
+     ectx->ec_iidx = save_iidx;
+ 
+     return res;
+ }
+ 
+ /*
   * Execute the instructions from an ISN_SUBSTITUTE command, which are in
   * "substitute_instr".
   */
***************
*** 4436,4441 ****
--- 4486,4499 ----
                }
  #endif
                break;
+           case ISN_INSTR:
+               {
+                   smsg("%s%4d INSTR", pfx, current);
+                   list_instructions("    ", iptr->isn_arg.instr,
+                                                               INT_MAX, NULL);
+                   msg("     -------------");
+               }
+               break;
            case ISN_SUBSTITUTE:
                {
                    subs_T *subs = &iptr->isn_arg.subs;
***************
*** 5225,5230 ****
--- 5283,5289 ----
        case VAR_UNKNOWN:
        case VAR_ANY:
        case VAR_VOID:
+       case VAR_INSTR:
            break;
      }
      return FALSE;
*** ../vim-8.2.2841/src/proto/vim9execute.pro   2021-04-19 16:48:44.431055514 
+0200
--- src/proto/vim9execute.pro   2021-05-07 16:02:15.324738264 +0200
***************
*** 4,9 ****
--- 4,10 ----
  char_u *char_from_string(char_u *str, varnumber_T index);
  char_u *string_slice(char_u *str, varnumber_T first, varnumber_T last, int 
exclusive);
  int fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx);
+ int exe_typval_instr(typval_T *tv, typval_T *rettv);
  char_u *exe_substitute_instr(void);
  int call_def_function(ufunc_T *ufunc, int argc_arg, typval_T *argv, partial_T 
*partial, typval_T *rettv);
  void ex_disassemble(exarg_T *eap);
*** ../vim-8.2.2841/src/eval.c  2021-04-28 20:00:35.014355562 +0200
--- src/eval.c  2021-05-07 16:49:04.853854664 +0200
***************
*** 309,314 ****
--- 309,318 ----
                return FAIL;
        }
      }
+     else if (expr->v_type == VAR_INSTR)
+     {
+       return exe_typval_instr(expr, rettv);
+     }
      else
      {
        s = tv_get_string_buf_chk(expr, buf);
***************
*** 1510,1515 ****
--- 1514,1520 ----
            case VAR_SPECIAL:
            case VAR_JOB:
            case VAR_CHANNEL:
+           case VAR_INSTR:
                break;
  
            case VAR_BLOB:
***************
*** 4084,4089 ****
--- 4089,4095 ----
        case VAR_SPECIAL:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
            if (verbose)
                emsg(_(e_cannot_index_special_variable));
            return FAIL;
***************
*** 4177,4182 ****
--- 4183,4189 ----
        case VAR_SPECIAL:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
            break; // not evaluating, skipping over subscript
  
        case VAR_NUMBER:
***************
*** 5067,5072 ****
--- 5074,5084 ----
            }
            break;
  
+       case VAR_INSTR:
+           *tofree = NULL;
+           r = (char_u *)"instructions";
+           break;
+ 
        case VAR_FLOAT:
  #ifdef FEAT_FLOAT
            *tofree = NULL;
***************
*** 5987,5992 ****
--- 5999,6005 ----
        case VAR_SPECIAL:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
            copy_tv(from, to);
            break;
        case VAR_LIST:
*** ../vim-8.2.2841/src/evalfunc.c      2021-04-02 18:55:52.058322772 +0200
--- src/evalfunc.c      2021-05-07 16:50:29.513613937 +0200
***************
*** 2989,2994 ****
--- 2989,2995 ----
        case VAR_UNKNOWN:
        case VAR_ANY:
        case VAR_VOID:
+       case VAR_INSTR:
            internal_error_no_abort("f_empty(UNKNOWN)");
            n = TRUE;
            break;
***************
*** 6303,6308 ****
--- 6304,6310 ----
        case VAR_PARTIAL:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
            emsg(_("E701: Invalid type for len()"));
            break;
      }
***************
*** 10215,10220 ****
--- 10217,10223 ----
        case VAR_JOB:     n = VAR_TYPE_JOB; break;
        case VAR_CHANNEL: n = VAR_TYPE_CHANNEL; break;
        case VAR_BLOB:    n = VAR_TYPE_BLOB; break;
+       case VAR_INSTR:   n = VAR_TYPE_INSTR; break;
        case VAR_UNKNOWN:
        case VAR_ANY:
        case VAR_VOID:
*** ../vim-8.2.2841/src/vim.h   2021-04-26 21:14:12.713924760 +0200
--- src/vim.h   2021-05-07 16:50:40.873581896 +0200
***************
*** 2030,2035 ****
--- 2030,2036 ----
  #define VAR_TYPE_JOB      8
  #define VAR_TYPE_CHANNEL    9
  #define VAR_TYPE_BLOB     10
+ #define VAR_TYPE_INSTR            11
  
  #define DICT_MAXNEST 100      // maximum nesting of lists and dicts
  
*** ../vim-8.2.2841/src/evalvars.c      2021-04-19 20:49:58.156857538 +0200
--- src/evalvars.c      2021-05-07 16:37:44.703664554 +0200
***************
*** 1912,1917 ****
--- 1912,1918 ----
        case VAR_SPECIAL:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
            break;
  
        case VAR_BLOB:
*** ../vim-8.2.2841/src/typval.c        2021-04-10 21:45:42.938892687 +0200
--- src/typval.c        2021-05-07 16:43:08.430865423 +0200
***************
*** 91,96 ****
--- 91,97 ----
            case VAR_VOID:
            case VAR_BOOL:
            case VAR_SPECIAL:
+           case VAR_INSTR:
                break;
        }
        vim_free(varp);
***************
*** 153,158 ****
--- 154,160 ----
            case VAR_UNKNOWN:
            case VAR_ANY:
            case VAR_VOID:
+           case VAR_INSTR:
                break;
        }
        varp->v_lock = 0;
***************
*** 236,241 ****
--- 238,244 ----
        case VAR_UNKNOWN:
        case VAR_ANY:
        case VAR_VOID:
+       case VAR_INSTR:
            internal_error_no_abort("tv_get_number(UNKNOWN)");
            break;
      }
***************
*** 333,338 ****
--- 336,342 ----
        case VAR_UNKNOWN:
        case VAR_ANY:
        case VAR_VOID:
+       case VAR_INSTR:
            internal_error_no_abort("tv_get_float(UNKNOWN)");
            break;
      }
***************
*** 514,519 ****
--- 518,524 ----
        case VAR_UNKNOWN:
        case VAR_ANY:
        case VAR_VOID:
+       case VAR_INSTR:
            emsg(_(e_inval_string));
            break;
      }
***************
*** 614,619 ****
--- 619,628 ----
                ++to->vval.v_channel->ch_refcount;
            break;
  #endif
+       case VAR_INSTR:
+           to->vval.v_instr = from->vval.v_instr;
+           break;
+ 
        case VAR_STRING:
        case VAR_FUNC:
            if (from->vval.v_string == NULL)
***************
*** 1116,1121 ****
--- 1125,1132 ----
  #ifdef FEAT_JOB_CHANNEL
            return tv1->vval.v_channel == tv2->vval.v_channel;
  #endif
+       case VAR_INSTR:
+           return tv1->vval.v_instr == tv2->vval.v_instr;
  
        case VAR_PARTIAL:
            return tv1->vval.v_partial == tv2->vval.v_partial;
*** ../vim-8.2.2841/src/vim9type.c      2021-04-13 20:53:09.846201149 +0200
--- src/vim9type.c      2021-05-07 16:58:51.892245751 +0200
***************
*** 950,955 ****
--- 950,956 ----
        case VAR_BLOB:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
            break;  // not composite is always OK
        case VAR_LIST:
        case VAR_DICT:
***************
*** 1097,1102 ****
--- 1098,1104 ----
        case VAR_CHANNEL: return "channel";
        case VAR_LIST: return "list";
        case VAR_DICT: return "dict";
+       case VAR_INSTR: return "instr";
  
        case VAR_FUNC:
        case VAR_PARTIAL: return "func";
*** ../vim-8.2.2841/src/testing.c       2021-04-02 18:55:52.058322772 +0200
--- src/testing.c       2021-05-07 16:51:01.009525276 +0200
***************
*** 1023,1028 ****
--- 1023,1029 ----
        case VAR_FLOAT:
        case VAR_SPECIAL:
        case VAR_STRING:
+       case VAR_INSTR:
            break;
        case VAR_JOB:
  #ifdef FEAT_JOB_CHANNEL
*** ../vim-8.2.2841/src/viminfo.c       2021-02-10 19:22:12.132400451 +0100
--- src/viminfo.c       2021-05-07 16:59:07.928203253 +0200
***************
*** 1376,1381 ****
--- 1376,1382 ----
                    case VAR_PARTIAL:
                    case VAR_JOB:
                    case VAR_CHANNEL:
+                   case VAR_INSTR:
                                     continue;
                }
                fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
*** ../vim-8.2.2841/src/if_py_both.h    2021-02-21 19:12:43.018019657 +0100
--- src/if_py_both.h    2021-05-07 16:59:37.992123722 +0200
***************
*** 6425,6430 ****
--- 6425,6431 ----
        case VAR_VOID:
        case VAR_CHANNEL:
        case VAR_JOB:
+       case VAR_INSTR:
            Py_INCREF(Py_None);
            return Py_None;
        case VAR_BOOL:
*** ../vim-8.2.2841/src/json.c  2021-02-08 21:53:05.592963320 +0100
--- src/json.c  2021-05-07 17:00:01.392061945 +0200
***************
*** 230,235 ****
--- 230,236 ----
        case VAR_PARTIAL:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
            semsg(_(e_cannot_json_encode_str), vartype_name(val->v_type));
            return FAIL;
  
*** ../vim-8.2.2841/src/testdir/test_vim9_disassemble.vim       2021-05-05 
21:31:36.068018579 +0200
--- src/testdir/test_vim9_disassemble.vim       2021-05-07 17:44:36.216903993 
+0200
***************
*** 140,145 ****
--- 140,174 ----
          res)
  enddef
  
+ 
+ def s:SearchPair()
+   var col = 8
+   searchpair("{", "", "}", "", "col('.') > col")
+ enddef
+ 
+ def Test_disassemble_seachpair()
+   var res = execute('disass s:SearchPair')
+   assert_match('<SNR>\d*_SearchPair.*' ..
+         ' var col = 8\_s*' ..
+         '\d STORE 8 in $0\_s*' ..
+         ' searchpair("{", "", "}", "", "col(''.'') > col")\_s*' ..
+         '\d PUSHS "{"\_s*' ..
+         '\d PUSHS ""\_s*' ..
+         '\d PUSHS "}"\_s*' ..
+         '\d PUSHS ""\_s*' ..
+         '\d INSTR\_s*' ..
+         '  0 PUSHS "."\_s*' ..
+         '  1 BCALL col(argc 1)\_s*' ..
+         '  2 LOAD $0\_s*' ..
+         '  3 COMPARENR >\_s*' ..
+         ' -------------\_s*' ..
+         '\d BCALL searchpair(argc 5)\_s*' ..
+         '\d DROP\_s*' ..
+         '\d RETURN 0',
+         res)
+ enddef
+ 
+ 
  def s:RedirVar()
    var result: string
    redir =>> result
*** ../vim-8.2.2841/src/testdir/test_vim9_builtin.vim   2021-05-03 
21:40:05.011799095 +0200
--- src/testdir/test_vim9_builtin.vim   2021-05-07 17:52:35.119650127 +0200
***************
*** 974,979 ****
--- 974,993 ----
    bwipe!
  enddef
  
+ def Test_searchpair()
+   new
+   setline(1, "here { and } there")
+   normal f{
+   var col = 15
+   assert_equal(1, searchpair('{', '', '}', '', 'col(".") > col'))
+   assert_equal(12, col('.'))
+   col = 8
+   normal 0f{
+   assert_equal(0, searchpair('{', '', '}', '', 'col(".") > col'))
+   assert_equal(6, col('.'))
+   bwipe!
+ enddef
+ 
  def Test_set_get_bufline()
    # similar to Test_setbufline_getbufline()
    var lines =<< trim END
*** ../vim-8.2.2841/src/version.c       2021-05-07 15:00:14.197520296 +0200
--- src/version.c       2021-05-07 17:55:06.431598365 +0200
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     2842,
  /**/

-- 
A man is incomplete until he's married ... and then he's finished!

 /// 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/202105071556.147FuTw61410303%40masaka.moolenaar.net.

Raspunde prin e-mail lui