# HG changeset patch # User Bram Moolenaar # Date 1609433104 -3600 # Node ID bb0c53f4ef8b79388be345310cf6806e0bcaf95b # Parent 4ac86caf4c42a7e41942420c3577ce45717dc6d8 patch 8.2.2254: Vim9: bool option type is number Commit: https://github.com/vim/vim/commit/dd1f426bd617ac6a775f2e7795ff0b159e3fa315 Author: Bram Moolenaar 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) diff --git a/src/evalvars.c b/src/evalvars.c --- 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; diff --git a/src/if_mzsch.c b/src/if_mzsch.c --- 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 diff --git a/src/if_ruby.c b/src/if_ruby.c --- 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); diff --git a/src/option.c b/src/option.c --- 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 diff --git a/src/option.h b/src/option.h --- 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 diff --git a/src/proto/option.pro b/src/proto/option.pro --- 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); diff --git a/src/spell.c b/src/spell.c --- 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"); diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim --- 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 diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim --- 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 diff --git a/src/typval.c b/src/typval.c --- 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 diff --git a/src/version.c b/src/version.c --- 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, diff --git a/src/vim9compile.c b/src/vim9compile.c --- 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 == '$') {