changeset 19102:ba9f50bfda83 v8.2.0111

patch 8.2.0111: VAR_SPECIAL is also used for booleans Commit: https://github.com/vim/vim/commit/9b4a15d5dba354d2e1e02871470bad103f34769a Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jan 11 16:05:23 2020 +0100 patch 8.2.0111: VAR_SPECIAL is also used for booleans Problem: VAR_SPECIAL is also used for booleans. Solution: Add VAR_BOOL for better type checking.
author Bram Moolenaar <Bram@vim.org>
date Sat, 11 Jan 2020 16:15:04 +0100
parents 7c682fab000b
children 8d183ace1c33
files src/dict.c src/eval.c src/evalfunc.c src/evalvars.c src/if_lua.c src/if_mzsch.c src/if_py_both.h src/if_ruby.c src/json.c src/popupmenu.c src/proto/dict.pro src/structs.h src/testing.c src/version.c src/vim.h src/viminfo.c
diffstat 16 files changed, 87 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/src/dict.c
+++ b/src/dict.c
@@ -345,14 +345,14 @@ dict_add(dict_T *d, dictitem_T *item)
  * Returns FAIL when out of memory and when key already exists.
  */
     static int
-dict_add_number_special(dict_T *d, char *key, varnumber_T nr, int special)
+dict_add_number_special(dict_T *d, char *key, varnumber_T nr, vartype_T vartype)
 {
     dictitem_T	*item;
 
     item = dictitem_alloc((char_u *)key);
     if (item == NULL)
 	return FAIL;
-    item->di_tv.v_type = special ? VAR_SPECIAL : VAR_NUMBER;
+    item->di_tv.v_type = vartype;
     item->di_tv.vval.v_number = nr;
     if (dict_add(d, item) == FAIL)
     {
@@ -369,7 +369,7 @@ dict_add_number_special(dict_T *d, char 
     int
 dict_add_number(dict_T *d, char *key, varnumber_T nr)
 {
-    return dict_add_number_special(d, key, nr, FALSE);
+    return dict_add_number_special(d, key, nr, VAR_NUMBER);
 }
 
 /*
@@ -377,9 +377,9 @@ dict_add_number(dict_T *d, char *key, va
  * Returns FAIL when out of memory and when key already exists.
  */
     int
-dict_add_special(dict_T *d, char *key, varnumber_T nr)
+dict_add_bool(dict_T *d, char *key, varnumber_T nr)
 {
-    return dict_add_number_special(d, key, nr, TRUE);
+    return dict_add_number_special(d, key, nr, VAR_BOOL);
 }
 
 /*
--- a/src/eval.c
+++ b/src/eval.c
@@ -1246,7 +1246,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char
 
     // Can't do anything with a Funcref, Dict, v:true on the right.
     if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT
-						&& tv2->v_type != VAR_SPECIAL)
+		      && tv2->v_type != VAR_BOOL && tv2->v_type != VAR_SPECIAL)
     {
 	switch (tv1->v_type)
 	{
@@ -1254,6 +1254,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char
 	    case VAR_DICT:
 	    case VAR_FUNC:
 	    case VAR_PARTIAL:
+	    case VAR_BOOL:
 	    case VAR_SPECIAL:
 	    case VAR_JOB:
 	    case VAR_CHANNEL:
@@ -3016,6 +3017,7 @@ eval_index(
 		emsg(_(e_float_as_string));
 	    return FAIL;
 #endif
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	case VAR_JOB:
 	case VAR_CHANNEL:
@@ -3131,6 +3133,7 @@ eval_index(
 	    case VAR_FUNC:
 	    case VAR_PARTIAL:
 	    case VAR_FLOAT:
+	    case VAR_BOOL:
 	    case VAR_SPECIAL:
 	    case VAR_JOB:
 	    case VAR_CHANNEL:
@@ -3777,6 +3780,7 @@ tv_equal(
 	    s2 = tv_get_string_buf(tv2, buf2);
 	    return ((ic ? MB_STRICMP(s1, s2) : STRCMP(s1, s2)) == 0);
 
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	    return tv1->vval.v_number == tv2->vval.v_number;
 
@@ -4531,6 +4535,7 @@ echo_string_core(
 	    break;
 #endif
 
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	    *tofree = NULL;
 	    r = (char_u *)get_var_special_name(tv->vval.v_number);
@@ -5359,6 +5364,7 @@ free_tv(typval_T *varp)
 	    case VAR_NUMBER:
 	    case VAR_FLOAT:
 	    case VAR_UNKNOWN:
+	    case VAR_BOOL:
 	    case VAR_SPECIAL:
 		break;
 	}
@@ -5399,6 +5405,7 @@ clear_tv(typval_T *varp)
 		varp->vval.v_dict = NULL;
 		break;
 	    case VAR_NUMBER:
+	    case VAR_BOOL:
 	    case VAR_SPECIAL:
 		varp->vval.v_number = 0;
 		break;
@@ -5480,6 +5487,7 @@ tv_get_number_chk(typval_T *varp, int *d
 	case VAR_DICT:
 	    emsg(_("E728: Using a Dictionary as a Number"));
 	    break;
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	    return varp->vval.v_number == VVAL_TRUE ? 1 : 0;
 	case VAR_JOB:
@@ -5529,6 +5537,9 @@ tv_get_float(typval_T *varp)
 	case VAR_DICT:
 	    emsg(_("E894: Using a Dictionary as a Float"));
 	    break;
+	case VAR_BOOL:
+	    emsg(_("E362: Using a boolean value as a Float"));
+	    break;
 	case VAR_SPECIAL:
 	    emsg(_("E907: Using a special value as a Float"));
 	    break;
@@ -5618,6 +5629,7 @@ tv_get_string_buf_chk(typval_T *varp, ch
 	    if (varp->vval.v_string != NULL)
 		return varp->vval.v_string;
 	    return (char_u *)"";
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	    STRCPY(buf, get_var_special_name(varp->vval.v_number));
 	    return buf;
@@ -5744,6 +5756,7 @@ copy_tv(typval_T *from, typval_T *to)
     switch (from->v_type)
     {
 	case VAR_NUMBER:
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	    to->vval.v_number = from->vval.v_number;
 	    break;
@@ -5850,6 +5863,7 @@ item_copy(
 	case VAR_STRING:
 	case VAR_FUNC:
 	case VAR_PARTIAL:
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	case VAR_JOB:
 	case VAR_CHANNEL:
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -1067,7 +1067,7 @@ non_zero_arg(typval_T *argvars)
 {
     return ((argvars[0].v_type == VAR_NUMBER
 		&& argvars[0].vval.v_number != 0)
-	    || (argvars[0].v_type == VAR_SPECIAL
+	    || (argvars[0].v_type == VAR_BOOL
 		&& argvars[0].vval.v_number == VVAL_TRUE)
 	    || (argvars[0].v_type == VAR_STRING
 		&& argvars[0].vval.v_string != NULL
@@ -1811,6 +1811,7 @@ f_empty(typval_T *argvars, typval_T *ret
 	    n = argvars[0].vval.v_dict == NULL
 			|| argvars[0].vval.v_dict->dv_hashtab.ht_used == 0;
 	    break;
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	    n = argvars[0].vval.v_number != VVAL_TRUE;
 	    break;
@@ -4318,6 +4319,7 @@ f_len(typval_T *argvars, typval_T *rettv
 	    rettv->vval.v_number = dict_len(argvars[0].vval.v_dict);
 	    break;
 	case VAR_UNKNOWN:
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	case VAR_FLOAT:
 	case VAR_FUNC:
@@ -8341,20 +8343,15 @@ f_type(typval_T *argvars, typval_T *rett
 
     switch (argvars[0].v_type)
     {
-	case VAR_NUMBER: n = VAR_TYPE_NUMBER; break;
-	case VAR_STRING: n = VAR_TYPE_STRING; break;
+	case VAR_NUMBER:  n = VAR_TYPE_NUMBER; break;
+	case VAR_STRING:  n = VAR_TYPE_STRING; break;
 	case VAR_PARTIAL:
-	case VAR_FUNC:   n = VAR_TYPE_FUNC; break;
-	case VAR_LIST:   n = VAR_TYPE_LIST; break;
-	case VAR_DICT:   n = VAR_TYPE_DICT; break;
-	case VAR_FLOAT:  n = VAR_TYPE_FLOAT; break;
-	case VAR_SPECIAL:
-	     if (argvars[0].vval.v_number == VVAL_FALSE
-		     || argvars[0].vval.v_number == VVAL_TRUE)
-		 n = VAR_TYPE_BOOL;
-	     else
-		 n = VAR_TYPE_NONE;
-	     break;
+	case VAR_FUNC:    n = VAR_TYPE_FUNC; break;
+	case VAR_LIST:    n = VAR_TYPE_LIST; break;
+	case VAR_DICT:    n = VAR_TYPE_DICT; break;
+	case VAR_FLOAT:   n = VAR_TYPE_FLOAT; break;
+	case VAR_BOOL:	  n = VAR_TYPE_BOOL; break;
+	case VAR_SPECIAL: n = VAR_TYPE_NONE; break;
 	case VAR_JOB:     n = VAR_TYPE_JOB; break;
 	case VAR_CHANNEL: n = VAR_TYPE_CHANNEL; break;
 	case VAR_BLOB:    n = VAR_TYPE_BLOB; break;
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -118,8 +118,8 @@ static struct vimvar
     {VV_NAME("option_command",	 VAR_STRING), VV_RO},
     {VV_NAME("option_type",	 VAR_STRING), VV_RO},
     {VV_NAME("errors",		 VAR_LIST), 0},
-    {VV_NAME("false",		 VAR_SPECIAL), VV_RO},
-    {VV_NAME("true",		 VAR_SPECIAL), VV_RO},
+    {VV_NAME("false",		 VAR_BOOL), VV_RO},
+    {VV_NAME("true",		 VAR_BOOL), VV_RO},
     {VV_NAME("null",		 VAR_SPECIAL), VV_RO},
     {VV_NAME("none",		 VAR_SPECIAL), VV_RO},
     {VV_NAME("vim_did_enter",	 VAR_NUMBER), VV_RO},
@@ -1675,6 +1675,7 @@ item_lock(typval_T *tv, int deep, int lo
 	case VAR_FUNC:
 	case VAR_PARTIAL:
 	case VAR_FLOAT:
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	case VAR_JOB:
 	case VAR_CHANNEL:
--- a/src/if_lua.c
+++ b/src/if_lua.c
@@ -535,6 +535,7 @@ luaV_pushtypval(lua_State *L, typval_T *
 	case VAR_DICT:
 	    luaV_pushdict(L, tv->vval.v_dict);
 	    break;
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	    if (tv->vval.v_number <= VVAL_TRUE)
 		lua_pushinteger(L, (int) tv->vval.v_number);
@@ -564,7 +565,7 @@ luaV_totypval(lua_State *L, int pos, typ
     switch (lua_type(L, pos))
     {
 	case LUA_TBOOLEAN:
-	    tv->v_type = VAR_SPECIAL;
+	    tv->v_type = VAR_BOOL;
 	    tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos);
 	    break;
 	case LUA_TNIL:
--- a/src/if_mzsch.c
+++ b/src/if_mzsch.c
@@ -3136,7 +3136,7 @@ vim_to_mzscheme_impl(typval_T *vim_value
 	    MZ_GC_UNREG();
 	}
     }
-    else if (vim_value->v_type == VAR_SPECIAL)
+    else if (vim_value->v_type == VAR_BOOL || vim_value->v_type == VAR_SPECIAL)
     {
 	if (vim_value->vval.v_number <= VVAL_TRUE)
 	    result = scheme_make_integer((long)vim_value->vval.v_number);
@@ -3218,7 +3218,7 @@ mzscheme_to_vim_impl(Scheme_Object *obj,
     }
     else if (SCHEME_BOOLP(obj))
     {
-	tv->v_type = VAR_SPECIAL;
+	tv->v_type = VAR_BOOL;
 	tv->vval.v_number = SCHEME_TRUEP(obj);
     }
 # ifdef FEAT_FLOAT
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -844,23 +844,24 @@ VimToPython(typval_T *our_tv, int depth,
 	    }
 	}
     }
-    else if (our_tv->v_type == VAR_SPECIAL)
+    else if (our_tv->v_type == VAR_BOOL)
     {
 	if (our_tv->vval.v_number == VVAL_FALSE)
 	{
 	    ret = Py_False;
 	    Py_INCREF(ret);
 	}
-	else if (our_tv->vval.v_number == VVAL_TRUE)
+	else
 	{
 	    ret = Py_True;
 	    Py_INCREF(ret);
 	}
-	else
-	{
-	    Py_INCREF(Py_None);
-	    ret = Py_None;
-	}
+	return ret;
+    }
+    else if (our_tv->v_type == VAR_SPECIAL)
+    {
+	Py_INCREF(Py_None);
+	ret = Py_None;
 	return ret;
     }
     else if (our_tv->v_type == VAR_BLOB)
@@ -6389,6 +6390,7 @@ ConvertToPyObject(typval_T *tv)
 	case VAR_JOB:
 	    Py_INCREF(Py_None);
 	    return Py_None;
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	    switch (tv->vval.v_number)
 	    {
--- a/src/if_ruby.c
+++ b/src/if_ruby.c
@@ -1183,7 +1183,7 @@ vim_to_ruby(typval_T *tv)
 	    }
 	}
     }
-    else if (tv->v_type == VAR_SPECIAL)
+    else if (tv->v_type == VAR_BOOL || tv->v_type == VAR_SPECIAL)
     {
 	if (tv->vval.v_number == VVAL_TRUE)
 	    result = Qtrue;
@@ -1827,11 +1827,11 @@ ruby_convert_to_vim_value(VALUE val, typ
 	    rettv->vval.v_number = VVAL_NULL;
 	    break;
 	case T_TRUE:
-	    rettv->v_type = VAR_SPECIAL;
+	    rettv->v_type = VAR_BOOL;
 	    rettv->vval.v_number = VVAL_TRUE;
 	    break;
 	case T_FALSE:
-	    rettv->v_type = VAR_SPECIAL;
+	    rettv->v_type = VAR_BOOL;
 	    rettv->vval.v_number = VVAL_FALSE;
 	    break;
 	case T_BIGNUM:
--- a/src/json.c
+++ b/src/json.c
@@ -193,11 +193,17 @@ json_encode_item(garray_T *gap, typval_T
 
     switch (val->v_type)
     {
-	case VAR_SPECIAL:
+	case VAR_BOOL:
 	    switch (val->vval.v_number)
 	    {
 		case VVAL_FALSE: ga_concat(gap, (char_u *)"false"); break;
 		case VVAL_TRUE: ga_concat(gap, (char_u *)"true"); break;
+	    }
+	    break;
+
+	case VAR_SPECIAL:
+	    switch (val->vval.v_number)
+	    {
 		case VVAL_NONE: if ((options & JSON_JS) != 0
 					     && (options & JSON_NO_NONE) == 0)
 				    // empty item
@@ -818,7 +824,7 @@ json_decode_item(js_read_T *reader, typv
 			reader->js_used += 5;
 			if (cur_item != NULL)
 			{
-			    cur_item->v_type = VAR_SPECIAL;
+			    cur_item->v_type = VAR_BOOL;
 			    cur_item->vval.v_number = VVAL_FALSE;
 			}
 			retval = OK;
@@ -829,7 +835,7 @@ json_decode_item(js_read_T *reader, typv
 			reader->js_used += 4;
 			if (cur_item != NULL)
 			{
-			    cur_item->v_type = VAR_SPECIAL;
+			    cur_item->v_type = VAR_BOOL;
 			    cur_item->vval.v_number = VVAL_TRUE;
 			}
 			retval = OK;
--- a/src/popupmenu.c
+++ b/src/popupmenu.c
@@ -1076,7 +1076,7 @@ pum_set_event_info(dict_T *dict)
     dict_add_number(dict, "row", pum_row);
     dict_add_number(dict, "col", pum_col);
     dict_add_number(dict, "size", pum_size);
-    dict_add_special(dict, "scrollbar", pum_scrollbar ? VVAL_TRUE : VVAL_FALSE);
+    dict_add_bool(dict, "scrollbar", pum_scrollbar ? VVAL_TRUE : VVAL_FALSE);
 }
 #endif
 
--- a/src/proto/dict.pro
+++ b/src/proto/dict.pro
@@ -14,7 +14,7 @@ void dictitem_free(dictitem_T *item);
 dict_T *dict_copy(dict_T *orig, int deep, int copyID);
 int dict_add(dict_T *d, dictitem_T *item);
 int dict_add_number(dict_T *d, char *key, varnumber_T nr);
-int dict_add_special(dict_T *d, char *key, varnumber_T nr);
+int dict_add_bool(dict_T *d, char *key, varnumber_T nr);
 int dict_add_string(dict_T *d, char *key, char_u *str);
 int dict_add_string_len(dict_T *d, char *key, char_u *str, int len);
 int dict_add_list(dict_T *d, char *key, list_T *list);
--- a/src/structs.h
+++ b/src/structs.h
@@ -1313,7 +1313,8 @@ typedef enum
     VAR_LIST,	 // "v_list" is used
     VAR_DICT,	 // "v_dict" is used
     VAR_FLOAT,	 // "v_float" is used
-    VAR_SPECIAL, // "v_number" is used
+    VAR_BOOL,	 // "v_number" is VVAL_FALSE or VVAL_TRUE
+    VAR_SPECIAL, // "v_number" is VVAL_NONE or VVAL_NULL
     VAR_JOB,	 // "v_job" is used
     VAR_CHANNEL, // "v_channel" is used
     VAR_BLOB,	 // "v_blob" is used
--- a/src/testing.c
+++ b/src/testing.c
@@ -222,7 +222,7 @@ assert_bool(typval_T *argvars, int isTru
     int		error = FALSE;
     garray_T	ga;
 
-    if (argvars[0].v_type == VAR_SPECIAL
+    if (argvars[0].v_type == VAR_BOOL
 	    && argvars[0].vval.v_number == (isTrue ? VVAL_TRUE : VVAL_FALSE))
 	return 0;
     if (argvars[0].v_type != VAR_NUMBER
@@ -760,6 +760,7 @@ f_test_refcount(typval_T *argvars, typva
 	case VAR_UNKNOWN:
 	case VAR_NUMBER:
 	case VAR_FLOAT:
+	case VAR_BOOL:
 	case VAR_SPECIAL:
 	case VAR_STRING:
 	    break;
--- a/src/version.c
+++ b/src/version.c
@@ -743,6 +743,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    111,
+/**/
     110,
 /**/
     109,
--- a/src/vim.h
+++ b/src/vim.h
@@ -2019,11 +2019,11 @@ typedef int sock_T;
 #define VV_ARGV		93
 #define VV_LEN		94	// number of v: vars
 
-// used for v_number in VAR_SPECIAL
-#define VVAL_FALSE	0L
-#define VVAL_TRUE	1L
-#define VVAL_NONE	2L
-#define VVAL_NULL	3L
+// used for v_number in VAR_BOOL and VAR_SPECIAL
+#define VVAL_FALSE	0L	// VAR_BOOL
+#define VVAL_TRUE	1L	// VAR_BOOL
+#define VVAL_NONE	2L	// VAR_SPECIAL
+#define VVAL_NULL	3L	// VAR_SPECIAL
 
 // Type values for type().
 #define VAR_TYPE_NUMBER	    0
--- a/src/viminfo.c
+++ b/src/viminfo.c
@@ -1233,7 +1233,12 @@ read_viminfo_varlist(vir_T *virp, int wr
 		    (void)string2float(tab + 1, &tv.vval.v_float);
 #endif
 		else
+		{
 		    tv.vval.v_number = atol((char *)tab + 1);
+		    if (type == VAR_SPECIAL && (tv.vval.v_number == VVAL_FALSE
+					     || tv.vval.v_number == VVAL_TRUE))
+			tv.v_type = VAR_BOOL;
+		}
 		if (type == VAR_DICT || type == VAR_LIST)
 		{
 		    typval_T *etv = eval_expr(tv.vval.v_string, NULL);
@@ -1312,12 +1317,13 @@ write_viminfo_varlist(FILE *fp)
 	    {
 		switch (this_var->di_tv.v_type)
 		{
-		    case VAR_STRING: s = "STR"; break;
-		    case VAR_NUMBER: s = "NUM"; break;
-		    case VAR_FLOAT:  s = "FLO"; break;
-		    case VAR_DICT:   s = "DIC"; break;
-		    case VAR_LIST:   s = "LIS"; break;
-		    case VAR_BLOB:   s = "BLO"; break;
+		    case VAR_STRING:  s = "STR"; break;
+		    case VAR_NUMBER:  s = "NUM"; break;
+		    case VAR_FLOAT:   s = "FLO"; break;
+		    case VAR_DICT:    s = "DIC"; break;
+		    case VAR_LIST:    s = "LIS"; break;
+		    case VAR_BLOB:    s = "BLO"; break;
+		    case VAR_BOOL:    s = "XPL"; break;  // backwards compat.
 		    case VAR_SPECIAL: s = "XPL"; break;
 
 		    case VAR_UNKNOWN:
@@ -1328,8 +1334,10 @@ write_viminfo_varlist(FILE *fp)
 				     continue;
 		}
 		fprintf(fp, "!%s\t%s\t", this_var->di_key, s);
-		if (this_var->di_tv.v_type == VAR_SPECIAL)
+		if (this_var->di_tv.v_type == VAR_BOOL
+				      || this_var->di_tv.v_type == VAR_SPECIAL)
 		{
+		    // do not use "v:true" but "1"
 		    sprintf((char *)numbuf, "%ld",
 					  (long)this_var->di_tv.vval.v_number);
 		    p = numbuf;