]> granicus.if.org Git - vim/commitdiff
patch 8.2.2842: Vim9: skip argument to searchpair() is not compiled v8.2.2842
authorBram Moolenaar <Bram@vim.org>
Fri, 7 May 2021 15:55:55 +0000 (17:55 +0200)
committerBram Moolenaar <Bram@vim.org>
Fri, 7 May 2021 15:55:55 +0000 (17:55 +0200)
Problem:    Vim9: skip argument to searchpair() is not compiled.
Solution:   Add VAR_INSTR.

18 files changed:
src/eval.c
src/evalfunc.c
src/evalvars.c
src/if_py_both.h
src/json.c
src/proto/vim9execute.pro
src/structs.h
src/testdir/test_vim9_builtin.vim
src/testdir/test_vim9_disassemble.vim
src/testing.c
src/typval.c
src/version.c
src/vim.h
src/vim9.h
src/vim9compile.c
src/vim9execute.c
src/vim9type.c
src/viminfo.c

index f25454960d39bc4c90965e65b0ce483adaf3f450..bf9e8ee7215b115eae1875ea8667faf67a30350b 100644 (file)
@@ -309,6 +309,10 @@ eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
                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,6 +1514,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
            case VAR_SPECIAL:
            case VAR_JOB:
            case VAR_CHANNEL:
+           case VAR_INSTR:
                break;
 
            case VAR_BLOB:
@@ -4084,6 +4089,7 @@ check_can_index(typval_T *rettv, int evaluate, int verbose)
        case VAR_SPECIAL:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
            if (verbose)
                emsg(_(e_cannot_index_special_variable));
            return FAIL;
@@ -4177,6 +4183,7 @@ eval_index_inner(
        case VAR_SPECIAL:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
            break; // not evaluating, skipping over subscript
 
        case VAR_NUMBER:
@@ -5067,6 +5074,11 @@ echo_string_core(
            }
            break;
 
+       case VAR_INSTR:
+           *tofree = NULL;
+           r = (char_u *)"instructions";
+           break;
+
        case VAR_FLOAT:
 #ifdef FEAT_FLOAT
            *tofree = NULL;
@@ -5987,6 +5999,7 @@ item_copy(
        case VAR_SPECIAL:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
            copy_tv(from, to);
            break;
        case VAR_LIST:
index 5383d098f4a5528777ab33bae51be0065c596ff2..a0caf3dce8bf738289eb68339d307efeaeb93de5 100644 (file)
@@ -2989,6 +2989,7 @@ f_empty(typval_T *argvars, typval_T *rettv)
        case VAR_UNKNOWN:
        case VAR_ANY:
        case VAR_VOID:
+       case VAR_INSTR:
            internal_error_no_abort("f_empty(UNKNOWN)");
            n = TRUE;
            break;
@@ -6303,6 +6304,7 @@ f_len(typval_T *argvars, typval_T *rettv)
        case VAR_PARTIAL:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
            emsg(_("E701: Invalid type for len()"));
            break;
     }
@@ -10215,6 +10217,7 @@ f_type(typval_T *argvars, typval_T *rettv)
        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:
index 1b0b7d0c98c48083f35ce944de4f383c92f11c8e..f3b4da222bf36e1e452d9f6524ef765cb4e01586 100644 (file)
@@ -1912,6 +1912,7 @@ item_lock(typval_T *tv, int deep, int lock, int check_refcount)
        case VAR_SPECIAL:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
            break;
 
        case VAR_BLOB:
index 9dbff1cbfb7fcf16d2b64174904c94087cdbc3f4..7f38e175b412c997e91fd0d780cbfe3915cb5d82 100644 (file)
@@ -6425,6 +6425,7 @@ ConvertToPyObject(typval_T *tv)
        case VAR_VOID:
        case VAR_CHANNEL:
        case VAR_JOB:
+       case VAR_INSTR:
            Py_INCREF(Py_None);
            return Py_None;
        case VAR_BOOL:
index dba003eae78a1e18fb9fe809b0bb5b6f122b55b1..25349b7551415ed52f07540521eb352a3ac90ded 100644 (file)
@@ -230,6 +230,7 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
        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;
 
index 46b314c8b1bda8686ec35fd762cb688f70b5cb89..4b6444a347a610c187266bb3875e5433cba99a3e 100644 (file)
@@ -4,6 +4,7 @@ void funcstack_check_refcount(funcstack_T *funcstack);
 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);
index 8da7c7b0cff597b9e9357820d6abc95c387b3965..9861bb601d975b5a6421339ae51f61db35ba9904 100644 (file)
@@ -1371,6 +1371,7 @@ typedef struct cbq_S cbq_T;
 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,6 +1390,7 @@ typedef enum
     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,6 +1431,7 @@ typedef struct
        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;
 
index 46fe3e5ca8d0c98718c7e8eb5c8ec6741920f6db..3232d9b3b7e921007da9b46a7963011106a8051f 100644 (file)
@@ -974,6 +974,20 @@ def Test_searchcount()
   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
index e7314e43f37ae7f2469aceb872cfc2485ae40b58..c4482a5d9cedd31a2e214368b97eaf7b0110ad16 100644 (file)
@@ -140,6 +140,35 @@ def Test_disassemble_substitute()
         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
index 740923735c0d60bfb170fb2e66d457653707b1fd..cded3c73a0aa41b58ca87a2f4af2d28fedf5471a 100644 (file)
@@ -1023,6 +1023,7 @@ f_test_refcount(typval_T *argvars, typval_T *rettv)
        case VAR_FLOAT:
        case VAR_SPECIAL:
        case VAR_STRING:
+       case VAR_INSTR:
            break;
        case VAR_JOB:
 #ifdef FEAT_JOB_CHANNEL
index f4af61a1731a83360100fc6f1885d1ad72b9c01c..4bde94e19221f9e9a816fa841cf3b26358655450 100644 (file)
@@ -91,6 +91,7 @@ free_tv(typval_T *varp)
            case VAR_VOID:
            case VAR_BOOL:
            case VAR_SPECIAL:
+           case VAR_INSTR:
                break;
        }
        vim_free(varp);
@@ -153,6 +154,7 @@ clear_tv(typval_T *varp)
            case VAR_UNKNOWN:
            case VAR_ANY:
            case VAR_VOID:
+           case VAR_INSTR:
                break;
        }
        varp->v_lock = 0;
@@ -236,6 +238,7 @@ tv_get_bool_or_number_chk(typval_T *varp, int *denote, int want_bool)
        case VAR_UNKNOWN:
        case VAR_ANY:
        case VAR_VOID:
+       case VAR_INSTR:
            internal_error_no_abort("tv_get_number(UNKNOWN)");
            break;
     }
@@ -333,6 +336,7 @@ tv_get_float(typval_T *varp)
        case VAR_UNKNOWN:
        case VAR_ANY:
        case VAR_VOID:
+       case VAR_INSTR:
            internal_error_no_abort("tv_get_float(UNKNOWN)");
            break;
     }
@@ -514,6 +518,7 @@ tv_get_string_buf_chk_strict(typval_T *varp, char_u *buf, int strict)
        case VAR_UNKNOWN:
        case VAR_ANY:
        case VAR_VOID:
+       case VAR_INSTR:
            emsg(_(e_inval_string));
            break;
     }
@@ -614,6 +619,10 @@ copy_tv(typval_T *from, typval_T *to)
                ++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,6 +1125,8 @@ tv_equal(
 #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;
index 4770cb305d0c333b420c8b82b5d970307939ea88..12aace894d70bd2f53449c741fb20d70305a14fe 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2842,
 /**/
     2841,
 /**/
index ead0c56c942ed10780b601af234b836a8f6ff53b..368cf3256c9aa1d571317d2bb380a36055ff7e2f 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -2030,6 +2030,7 @@ typedef int sock_T;
 #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
 
index 94cc243ddcae50d7322726fa64fa6091e73667a1..9f45ea41252afa7d284e2258681bcb16cd2a57be 100644 (file)
@@ -20,6 +20,7 @@ typedef enum {
     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,6 +412,7 @@ struct isn_S {
        isn_outer_T         outer;
        subs_T              subs;
        cexpr_T             cexpr;
+       isn_T               *instr;
     } isn_arg;
 };
 
index f89b0d7d35446ec341cab859b18816b7ea0801c1..03aca55b8cfd4982b1d4ed9dec6308a674297303 100644 (file)
@@ -615,6 +615,7 @@ may_generate_2STRING(int offset, cctx_T *cctx)
        case VAR_DICT:
        case VAR_JOB:
        case VAR_CHANNEL:
+       case VAR_INSTR:
                         to_string_error((*type)->tt_type);
                         return FAIL;
     }
@@ -3097,16 +3098,72 @@ theend:
     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)
+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,10 +3180,21 @@ compile_arguments(char_u **arg, cctx_T *cctx, int *argcount)
            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,6 +3243,7 @@ compile_call(
     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,8 +3285,11 @@ compile_call(
     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) == FAIL)
+    if (compile_arguments(arg, cctx, &argcount, is_searchpair) == FAIL)
        goto theend;
 
     is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
@@ -4027,7 +4099,7 @@ compile_subscript(
            type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
 
            *arg = skipwhite(p + 1);
-           if (compile_arguments(arg, cctx, &argcount) == FAIL)
+           if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL)
                return FAIL;
            if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
                return FAIL;
@@ -4080,7 +4152,7 @@ compile_subscript(
                    return FAIL;
                }
                *arg = skipwhite(*arg + 1);
-               if (compile_arguments(arg, cctx, &argcount) == FAIL)
+               if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL)
                    return FAIL;
 
                // Move the instructions for the arguments to before the
@@ -6728,6 +6800,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
                    case VAR_ANY:
                    case VAR_PARTIAL:
                    case VAR_VOID:
+                   case VAR_INSTR:
                    case VAR_SPECIAL:  // cannot happen
                        generate_PUSHNR(cctx, 0);
                        break;
@@ -8536,16 +8609,6 @@ theend:
 }
 
 
-    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/
  */
@@ -8568,13 +8631,13 @@ compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
            int         expr_res;
            int         trailing_error;
            int         instr_count;
-           isn_T       *instr = NULL;
+           isn_T       *instr;
            isn_T       *isn;
 
            cmd += 3;
            end = skip_substitute(cmd, delimiter);
 
-           // Temporarily reset the list of instructions so that the jumps
+           // 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,7 +8655,6 @@ compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
                    semsg(_(e_trailing_arg), cmd);
                clear_instr_ga(&cctx->ctx_instr);
                cctx->ctx_instr = save_ga;
-               vim_free(instr);
                return NULL;
            }
 
@@ -9555,6 +9617,17 @@ delete_instr(isn_T *isn)
            }
            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;
+
        case ISN_LOADS:
        case ISN_STORES:
            vim_free(isn->isn_arg.loadstore.ls_name);
index c8586b384628c3701a6ab03ec96a71e001033c06..29cd5fc67ae3a2b075545e6ac8ec42713356a67a 100644 (file)
@@ -1259,6 +1259,12 @@ fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx)
     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,6 +1385,23 @@ exec_instructions(ectx_T *ectx)
                }
                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:
                {
@@ -3996,6 +4019,33 @@ done:
     return OK;
 }
 
+/*
+ * 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,6 +4486,14 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
                }
 #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,6 +5283,7 @@ tv2bool(typval_T *tv)
        case VAR_UNKNOWN:
        case VAR_ANY:
        case VAR_VOID:
+       case VAR_INSTR:
            break;
     }
     return FALSE;
index 8b0f2f15e2b46c2fe57bc4197b5a622f641408fc..4dec1e7704416d61ebb47dfbfbaa555ea2a9c65e 100644 (file)
@@ -950,6 +950,7 @@ equal_type(type_T *type1, type_T *type2)
        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,6 +1098,7 @@ vartype_name(vartype_T type)
        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";
index aca24317934995a0b0a5d3763213ca762af07b39..6b92cc64abfd884ebba8d3005662c0a5bffdd47e 100644 (file)
@@ -1376,6 +1376,7 @@ write_viminfo_varlist(FILE *fp)
                    case VAR_PARTIAL:
                    case VAR_JOB:
                    case VAR_CHANNEL:
+                   case VAR_INSTR:
                                     continue;
                }
                fprintf(fp, "!%s\t%s\t", this_var->di_key, s);