changeset 23422:bb0c53f4ef8b v8.2.2254

patch 8.2.2254: Vim9: bool option type is number Commit: https://github.com/vim/vim/commit/dd1f426bd617ac6a775f2e7795ff0b159e3fa315 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Dec 31 17:41:01 2020 +0100 patch 8.2.2254: Vim9: bool option type is number Problem: Vim9: bool option type is number. Solution: Have get_option_value() return a different value for bool and number options. (closes #7583)
author Bram Moolenaar <Bram@vim.org>
date Thu, 31 Dec 2020 17:45:04 +0100
parents 4ac86caf4c42
children 7481358c00ed
files src/evalvars.c src/if_mzsch.c src/if_ruby.c src/option.c src/option.h src/proto/option.pro src/spell.c src/testdir/test_vim9_assign.vim src/testdir/test_vim9_cmd.vim src/typval.c src/version.c src/vim9compile.c
diffstat 12 files changed, 106 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -1354,7 +1354,7 @@ ex_let_one(
 	else
 	{
 	    long	n = 0;
-	    int		opt_type;
+	    getoption_T	opt_type;
 	    long	numval;
 	    char_u	*stringval = NULL;
 	    char_u	*s = NULL;
@@ -1364,7 +1364,10 @@ ex_let_one(
 	    *p = NUL;
 
 	    opt_type = get_option_value(arg, &numval, &stringval, opt_flags);
-	    if ((opt_type == 1 || opt_type == -1)
+	    if ((opt_type == gov_bool
+			|| opt_type == gov_number
+			|| opt_type == gov_hidden_bool
+			|| opt_type == gov_hidden_number)
 			     && (tv->v_type != VAR_STRING || !in_vim9script()))
 		// number, possibly hidden
 		n = (long)tv_get_number(tv);
@@ -1377,8 +1380,9 @@ ex_let_one(
 
 	    if (op != NULL && *op != '=')
 	    {
-		if ((opt_type == 1 && *op == '.')
-			|| (opt_type == 0 && *op != '.'))
+		if (((opt_type == gov_bool || opt_type == gov_number)
+								 && *op == '.')
+			|| (opt_type == gov_string && *op != '.'))
 		{
 		    semsg(_(e_letwrong), op);
 		    failed = TRUE;  // don't set the value
@@ -1386,7 +1390,9 @@ ex_let_one(
 		}
 		else
 		{
-		    if (opt_type == 1)  // number
+		    // number, in legacy script also bool
+		    if (opt_type == gov_number
+				 || (opt_type == gov_bool && !in_vim9script()))
 		    {
 			switch (*op)
 			{
@@ -1397,7 +1403,8 @@ ex_let_one(
 			    case '%': n = (long)num_modulus(numval, n); break;
 			}
 		    }
-		    else if (opt_type == 0 && stringval != NULL && s != NULL)
+		    else if (opt_type == gov_string
+					     && stringval != NULL && s != NULL)
 		    {
 			// string
 			s = concat_str(stringval, s);
@@ -1409,7 +1416,7 @@ ex_let_one(
 
 	    if (!failed)
 	    {
-		if (opt_type != 0 || s != NULL)
+		if (opt_type != gov_string || s != NULL)
 		{
 		    set_option_value(arg, n, s, opt_flags);
 		    arg_end = p;
--- a/src/if_mzsch.c
+++ b/src/if_mzsch.c
@@ -1712,7 +1712,7 @@ get_option(void *data, int argc, Scheme_
     Vim_Prim	    *prim = (Vim_Prim *)data;
     long	    value;
     char	    *strval;
-    int		    rc;
+    getoption_T	    rc;
     Scheme_Object   *rval = NULL;
     Scheme_Object   *name = NULL;
     int		    opt_flags = 0;
@@ -1754,27 +1754,30 @@ get_option(void *data, int argc, Scheme_
 	    scheme_wrong_type(prim->name, "vim-buffer/window", 1, argc, argv);
     }
 
-    rc = get_option_value(BYTE_STRING_VALUE(name), &value, (char_u **)&strval, opt_flags);
+    rc = get_option_value(BYTE_STRING_VALUE(name), &value, (char_u **)&strval,
+								    opt_flags);
     curbuf = save_curb;
     curwin = save_curw;
 
     switch (rc)
     {
-    case 1:
+    case gov_bool:
+    case gov_number:
 	MZ_GC_UNREG();
 	return scheme_make_integer_value(value);
-    case 0:
+    case gov_string:
 	rval = scheme_make_byte_string(strval);
 	MZ_GC_CHECK();
 	vim_free(strval);
 	MZ_GC_UNREG();
 	return rval;
-    case -1:
-    case -2:
+    case gov_hidden_bool:
+    case gov_hidden_number:
+    case gov_hidden_string:
 	MZ_GC_UNREG();
 	raise_vim_exn(_("hidden option"));
 	//NOTREACHED
-    case -3:
+    case gov_unknown:
 	MZ_GC_UNREG();
 	raise_vim_exn(_("unknown option"));
 	//NOTREACHED
--- a/src/if_ruby.c
+++ b/src/if_ruby.c
@@ -865,13 +865,11 @@ ex_ruby(exarg_T *eap)
 vim_str2rb_enc_str(const char *s)
 {
 #if RUBY_VERSION >= 19
-    int isnum;
     long lval;
     char_u *sval;
     rb_encoding *enc;
 
-    isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
-    if (isnum == 0)
+    if (get_option_value((char_u *)"enc", &lval, &sval, 0) == gov_string)
     {
 	enc = rb_enc_find((char *)sval);
 	vim_free(sval);
@@ -886,14 +884,12 @@ vim_str2rb_enc_str(const char *s)
 eval_enc_string_protect(const char *str, int *state)
 {
 #if RUBY_VERSION >= 19
-    int isnum;
     long lval;
     char_u *sval;
     rb_encoding *enc;
     VALUE v;
 
-    isnum = get_option_value((char_u *)"enc", &lval, &sval, 0);
-    if (isnum == 0)
+    if (get_option_value((char_u *)"enc", &lval, &sval, 0) == gov_string)
     {
 	enc = rb_enc_find((char *)sval);
 	vim_free(sval);
--- a/src/option.c
+++ b/src/option.c
@@ -3834,13 +3834,15 @@ findoption(char_u *arg)
  * Get the value for an option.
  *
  * Returns:
- * Number or Toggle option: 1, *numval gets value.
- *	     String option: 0, *stringval gets allocated string.
- * Hidden Number or Toggle option: -1.
- *	     hidden String option: -2.
- *		   unknown option: -3.
+ * Number option: gov_number, *numval gets value.
+ * Tottle option: gov_bool,   *numval gets value.
+ * String option: gov_string, *stringval gets allocated string.
+ * Hidden Number option: gov_hidden_number.
+ * Hidden Toggle option: gov_hidden_bool.
+ * Hidden String option: gov_hidden_string.
+ * Unknown option: gov_unknown.
  */
-    int
+    getoption_T
 get_option_value(
     char_u	*name,
     long	*numval,
@@ -3851,16 +3853,17 @@ get_option_value(
     char_u	*varp;
 
     opt_idx = findoption(name);
-    if (opt_idx < 0)		    // unknown option
+    if (opt_idx < 0)		    // option not in the table
     {
 	int key;
 
 	if (STRLEN(name) == 4 && name[0] == 't' && name[1] == '_'
-		&& (key = find_key_option(name, FALSE)) != 0)
+				  && (key = find_key_option(name, FALSE)) != 0)
 	{
 	    char_u key_name[2];
 	    char_u *p;
 
+	    // check for a terminal option
 	    if (key < 0)
 	    {
 		key_name[0] = KEY2TERMCAP0(key);
@@ -3876,10 +3879,10 @@ get_option_value(
 	    {
 		if (stringval != NULL)
 		    *stringval = vim_strsave(p);
-		return 0;
+		return gov_string;
 	    }
 	}
-	return -3;
+	return gov_unknown;
     }
 
     varp = get_varp_scope(&(options[opt_idx]), opt_flags);
@@ -3887,7 +3890,7 @@ get_option_value(
     if (options[opt_idx].flags & P_STRING)
     {
 	if (varp == NULL)		    // hidden option
-	    return -2;
+	    return gov_hidden_string;
 	if (stringval != NULL)
 	{
 #ifdef FEAT_CRYPT
@@ -3899,11 +3902,12 @@ get_option_value(
 #endif
 		*stringval = vim_strsave(*(char_u **)(varp));
 	}
-	return 0;
+	return gov_string;
     }
 
     if (varp == NULL)		    // hidden option
-	return -1;
+	return (options[opt_idx].flags & P_NUM)
+					 ? gov_hidden_number : gov_hidden_bool;
     if (options[opt_idx].flags & P_NUM)
 	*numval = *(long *)varp;
     else
@@ -3915,7 +3919,7 @@ get_option_value(
 	else
 	    *numval = (long) *(int *)varp;
     }
-    return 1;
+    return (options[opt_idx].flags & P_NUM) ? gov_number : gov_bool;
 }
 #endif
 
--- a/src/option.h
+++ b/src/option.h
@@ -60,6 +60,17 @@
 #define P_RWINONLY   0x10000000L // only redraw current window
 #define P_MLE	     0x20000000L // under control of 'modelineexpr'
 
+// Returned by get_option_value().
+typedef enum {
+    gov_unknown,
+    gov_bool,
+    gov_number,
+    gov_string,
+    gov_hidden_bool,
+    gov_hidden_number,
+    gov_hidden_string
+} getoption_T;
+
 /*
  * Default values for 'errorformat'.
  * The "%f|%l| %m" one is used for when the contents of the quickfix window is
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -24,7 +24,7 @@ void set_option_sctx_idx(int opt_idx, in
 void set_term_option_sctx_idx(char *name, int opt_idx);
 void check_redraw(long_u flags);
 int findoption(char_u *arg);
-int get_option_value(char_u *name, long *numval, char_u **stringval, int opt_flags);
+getoption_T get_option_value(char_u *name, long *numval, char_u **stringval, int opt_flags);
 int get_option_value_strict(char_u *name, long *numval, char_u **stringval, int opt_type, void *from);
 char_u *option_iter_next(void **option, int opt_type);
 long_u get_option_flags(int opt_idx);
--- a/src/spell.c
+++ b/src/spell.c
@@ -3813,7 +3813,7 @@ ex_spelldump(exarg_T *eap)
 
     if (no_spell_checking(curwin))
 	return;
-    get_option_value((char_u*)"spl", &dummy, &spl, OPT_LOCAL);
+    (void)get_option_value((char_u*)"spl", &dummy, &spl, OPT_LOCAL);
 
     // Create a new empty buffer in a new window.
     do_cmdline_cmd((char_u *)"new");
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -45,6 +45,9 @@ def Test_assignment_bool()
     assert_equal(true, flag)
     flag = 1 && false
     assert_equal(false, flag)
+
+    var cp: bool = &cp
+    var fen: bool = &l:fen
   END
   CheckScriptSuccess(lines)
   CheckDefAndScriptFailure(['var x: bool = 2'], 'E1012:')
@@ -118,6 +121,8 @@ def Test_assignment()
   assert_equal('new', s:newVar)
 
   set ts=7
+  var ts: number = &ts
+  assert_equal(7, ts)
   &ts += 1
   assert_equal(8, &ts)
   &ts -= 3
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -590,7 +590,7 @@ def Test_command_modifier_other()
   unlet g:readFile
 
   noswapfile edit XnoSwap
-  assert_equal(0, &l:swapfile)
+  assert_equal(false, &l:swapfile)
   bwipe!
 
   var caught = false
--- a/src/typval.c
+++ b/src/typval.c
@@ -1083,7 +1083,7 @@ eval_option(
     char_u	*option_end;
     long	numval;
     char_u	*stringval;
-    int		opt_type;
+    getoption_T	opt_type;
     int		c;
     int		working = (**arg == '+');    // has("+option")
     int		ret = OK;
@@ -1109,7 +1109,7 @@ eval_option(
     opt_type = get_option_value(*arg, &numval,
 			       rettv == NULL ? NULL : &stringval, opt_flags);
 
-    if (opt_type == -3)			// invalid name
+    if (opt_type == gov_unknown)
     {
 	if (rettv != NULL)
 	    semsg(_(e_unknown_option), *arg);
@@ -1117,20 +1117,29 @@ eval_option(
     }
     else if (rettv != NULL)
     {
-	if (opt_type == -2)		// hidden string option
+	if (opt_type == gov_hidden_string)
 	{
 	    rettv->v_type = VAR_STRING;
 	    rettv->vval.v_string = NULL;
 	}
-	else if (opt_type == -1)	// hidden number option
+	else if (opt_type == gov_hidden_bool || opt_type == gov_hidden_number)
 	{
-	    rettv->v_type = VAR_NUMBER;
+	    rettv->v_type = in_vim9script() && opt_type == gov_hidden_bool
+						       ? VAR_BOOL : VAR_NUMBER;
 	    rettv->vval.v_number = 0;
 	}
-	else if (opt_type == 1)		// number option
+	else if (opt_type == gov_bool || opt_type == gov_number)
 	{
-	    rettv->v_type = VAR_NUMBER;
-	    rettv->vval.v_number = numval;
+	    if (in_vim9script() && opt_type == gov_bool)
+	    {
+		rettv->v_type = VAR_BOOL;
+		rettv->vval.v_number = numval ? VVAL_TRUE : VVAL_FALSE;
+	    }
+	    else
+	    {
+		rettv->v_type = VAR_NUMBER;
+		rettv->vval.v_number = numval;
+	    }
 	}
 	else				// string option
 	{
@@ -1138,7 +1147,9 @@ eval_option(
 	    rettv->vval.v_string = stringval;
 	}
     }
-    else if (working && (opt_type == -2 || opt_type == -1))
+    else if (working && (opt_type == gov_hidden_bool
+			|| opt_type == gov_hidden_number
+			|| opt_type == gov_hidden_string))
 	ret = FAIL;
 
     *option_end = c;		    // put back for error messages
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2254,
+/**/
     2253,
 /**/
     2252,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -5191,9 +5191,9 @@ get_var_dest(
 
     if (*name == '&')
     {
-	int	cc;
-	long	numval;
-	int	opt_type;
+	int		cc;
+	long		numval;
+	getoption_T	opt_type;
 
 	*dest = dest_option;
 	if (cmdidx == CMD_final || cmdidx == CMD_const)
@@ -5214,15 +5214,24 @@ get_var_dest(
 	opt_type = get_option_value(skip_option_env_lead(name),
 						    &numval, NULL, *opt_flags);
 	*p = cc;
-	if (opt_type == -3)
-	{
-	    semsg(_(e_unknown_option), name);
-	    return FAIL;
-	}
-	if (opt_type == -2 || opt_type == 0)
-	    *type = &t_string;
-	else
-	    *type = &t_number;	// both number and boolean option
+	switch (opt_type)
+	{
+	    case gov_unknown:
+		    semsg(_(e_unknown_option), name);
+		    return FAIL;
+	    case gov_string:
+	    case gov_hidden_string:
+		    *type = &t_string;
+		    break;
+	    case gov_bool:
+	    case gov_hidden_bool:
+		    *type = &t_bool;
+		    break;
+	    case gov_number:
+	    case gov_hidden_number:
+		    *type = &t_number;
+		    break;
+	}
     }
     else if (*name == '$')
     {