To: vim_dev@googlegroups.com Subject: Patch 8.2.2162 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2162 Problem: Vim9: Cannot load or store autoload variables. Solution: Add ISN_LOADAUTO and ISN_STOREAUTO. (closes #7485) Files: src/vim9compile.c, src/vim9.h, src/vim9execute.c, src/dict.c, src/eval.c, src/evalvars.c, src/proto/evalvars.pro, src/testdir/test_vim9_disassemble.vim, src/testdir/test_vim9_script.vim *** ../vim-8.2.2161/src/vim9compile.c 2020-12-18 19:49:52.349571840 +0100 --- src/vim9compile.c 2020-12-19 15:38:42.981882699 +0100 *************** *** 2535,2541 **** case 's': res = compile_load_scriptvar(cctx, name, NULL, NULL, error); break; ! case 'g': isn_type = ISN_LOADG; break; case 'w': isn_type = ISN_LOADW; break; case 't': isn_type = ISN_LOADT; break; case 'b': isn_type = ISN_LOADB; break; --- 2535,2551 ---- case 's': res = compile_load_scriptvar(cctx, name, NULL, NULL, error); break; ! case 'g': if (vim_strchr(name, AUTOLOAD_CHAR) == NULL) ! isn_type = ISN_LOADG; ! else ! { ! isn_type = ISN_LOADAUTO; ! vim_free(name); ! name = vim_strnsave(*arg, end - *arg); ! if (name == NULL) ! return FAIL; ! } ! break; case 'w': isn_type = ISN_LOADW; break; case 't': isn_type = ISN_LOADT; break; case 'b': isn_type = ISN_LOADB; break; *************** *** 2738,2744 **** if (compile_arguments(arg, cctx, &argcount) == FAIL) goto theend; ! is_autoload = vim_strchr(name, '#') != NULL; if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload) { int idx; --- 2748,2754 ---- if (compile_arguments(arg, cctx, &argcount) == FAIL) goto theend; ! is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL; if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload) { int idx; *************** *** 4986,4992 **** generate_LOAD(cctx, ISN_LOADOPT, 0, name, type); break; case dest_global: ! generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type); break; case dest_buffer: generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type); --- 4996,5005 ---- generate_LOAD(cctx, ISN_LOADOPT, 0, name, type); break; case dest_global: ! if (vim_strchr(name, AUTOLOAD_CHAR) == NULL) ! generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type); ! else ! generate_LOAD(cctx, ISN_LOADAUTO, 0, name, type); break; case dest_buffer: generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type); *************** *** 5198,5204 **** opt_flags); case dest_global: // include g: with the name, easier to execute that way ! return generate_STORE(cctx, ISN_STOREG, 0, name); case dest_buffer: // include b: with the name, easier to execute that way return generate_STORE(cctx, ISN_STOREB, 0, name); --- 5211,5218 ---- opt_flags); case dest_global: // include g: with the name, easier to execute that way ! return generate_STORE(cctx, vim_strchr(name, AUTOLOAD_CHAR) == NULL ! ? ISN_STOREG : ISN_STOREAUTO, 0, name); case dest_buffer: // include b: with the name, easier to execute that way return generate_STORE(cctx, ISN_STOREB, 0, name); *************** *** 8007,8012 **** --- 8021,8027 ---- { case ISN_DEF: case ISN_EXEC: + case ISN_LOADAUTO: case ISN_LOADB: case ISN_LOADENV: case ISN_LOADG: *************** *** 8017,8022 **** --- 8032,8038 ---- case ISN_PUSHFUNC: case ISN_PUSHS: case ISN_RANGE: + case ISN_STOREAUTO: case ISN_STOREB: case ISN_STOREENV: case ISN_STOREG: *** ../vim-8.2.2161/src/vim9.h 2020-12-18 19:49:52.349571840 +0100 --- src/vim9.h 2020-12-19 14:26:30.450999685 +0100 *************** *** 24,29 **** --- 24,30 ---- ISN_LOAD, // push local variable isn_arg.number ISN_LOADV, // push v: variable isn_arg.number ISN_LOADG, // push g: variable isn_arg.string + ISN_LOADAUTO, // push g: autoload variable isn_arg.string ISN_LOADB, // push b: variable isn_arg.string ISN_LOADW, // push w: variable isn_arg.string ISN_LOADT, // push t: variable isn_arg.string *************** *** 41,46 **** --- 42,48 ---- ISN_STORE, // pop into local variable isn_arg.number ISN_STOREV, // pop into v: variable isn_arg.number ISN_STOREG, // pop into global variable isn_arg.string + ISN_STOREAUTO, // pop into global autoload variable isn_arg.string ISN_STOREB, // pop into buffer-local variable isn_arg.string ISN_STOREW, // pop into window-local variable isn_arg.string ISN_STORET, // pop into tab-local variable isn_arg.string *** ../vim-8.2.2161/src/vim9execute.c 2020-12-18 19:49:52.349571840 +0100 --- src/vim9execute.c 2020-12-19 16:01:10.224915769 +0100 *************** *** 1391,1396 **** --- 1391,1411 ---- } break; + // load autoload variable + case ISN_LOADAUTO: + { + char_u *name = iptr->isn_arg.string; + + if (GA_GROW(&ectx.ec_stack, 1) == FAIL) + goto failed; + SOURCING_LNUM = iptr->isn_lnum; + if (eval_variable(name, STRLEN(name), + STACK_TV_BOT(0), NULL, TRUE, FALSE) == FAIL) + goto on_error; + ++ectx.ec_stack.ga_len; + } + break; + // load g:/b:/w:/t: namespace case ISN_LOADGDICT: case ISN_LOADBDICT: *************** *** 1611,1616 **** --- 1626,1639 ---- } break; + // store an autoload variable + case ISN_STOREAUTO: + SOURCING_LNUM = iptr->isn_lnum; + set_var(iptr->isn_arg.string, STACK_TV_BOT(-1), TRUE); + clear_tv(STACK_TV_BOT(-1)); + --ectx.ec_stack.ga_len; + break; + // store number in local variable case ISN_STORENR: tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx); *************** *** 3286,3291 **** --- 3309,3317 ---- iptr->isn_arg.loadstore.ls_name, si->sn_name); } break; + case ISN_LOADAUTO: + smsg("%4d LOADAUTO %s", current, iptr->isn_arg.string); + break; case ISN_LOADG: smsg("%4d LOADG g:%s", current, iptr->isn_arg.string); break; *************** *** 3337,3342 **** --- 3363,3371 ---- smsg("%4d STOREV v:%s", current, get_vim_var_name(iptr->isn_arg.number)); break; + case ISN_STOREAUTO: + smsg("%4d STOREAUTO %s", current, iptr->isn_arg.string); + break; case ISN_STOREG: smsg("%4d STOREG %s", current, iptr->isn_arg.string); break; *** ../vim-8.2.2161/src/dict.c 2020-12-15 21:41:53.141431375 +0100 --- src/dict.c 2020-12-19 16:17:34.510365354 +0100 *************** *** 1073,1079 **** && HI2DI(hi2)->di_tv.v_type == VAR_FUNC && var_wrong_func_name(hi2->hi_key, di1 == NULL)) break; ! if (!valid_varname(hi2->hi_key)) break; } if (di1 == NULL) --- 1073,1079 ---- && HI2DI(hi2)->di_tv.v_type == VAR_FUNC && var_wrong_func_name(hi2->hi_key, di1 == NULL)) break; ! if (!valid_varname(hi2->hi_key, TRUE)) break; } if (di1 == NULL) *** ../vim-8.2.2161/src/eval.c 2020-12-18 19:49:52.337571884 +0100 --- src/eval.c 2020-12-19 16:17:41.446343651 +0100 *************** *** 1049,1055 **** wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE && rettv->v_type == VAR_FUNC && var_wrong_func_name(key, lp->ll_di == NULL)) ! || !valid_varname(key); if (len != -1) key[len] = prevval; if (wrong) --- 1049,1055 ---- wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE && rettv->v_type == VAR_FUNC && var_wrong_func_name(key, lp->ll_di == NULL)) ! || !valid_varname(key, TRUE); if (len != -1) key[len] = prevval; if (wrong) *** ../vim-8.2.2161/src/evalvars.c 2020-12-18 15:37:57.248171925 +0100 --- src/evalvars.c 2020-12-19 16:22:34.353408599 +0100 *************** *** 3195,3202 **** goto failed; } ! // Make sure the variable name is valid. ! if (!valid_varname(varname)) goto failed; di = alloc(sizeof(dictitem_T) + STRLEN(varname)); --- 3195,3204 ---- goto failed; } ! // Make sure the variable name is valid. In Vim9 script an autoload ! // variable must be prefixed with "g:". ! if (!valid_varname(varname, !vim9script ! || STRNCMP(name, "g:", 2) == 0)) goto failed; di = alloc(sizeof(dictitem_T) + STRLEN(varname)); *************** *** 3349,3365 **** } /* ! * Check if a variable name is valid. * Return FALSE and give an error if not. */ int ! valid_varname(char_u *varname) { char_u *p; for (p = varname; *p != NUL; ++p) if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p)) ! && *p != AUTOLOAD_CHAR) { semsg(_(e_illvar), varname); return FALSE; --- 3351,3367 ---- } /* ! * Check if a variable name is valid. When "autoload" is true "#" is allowed. * Return FALSE and give an error if not. */ int ! valid_varname(char_u *varname, int autoload) { char_u *p; for (p = varname; *p != NUL; ++p) if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p)) ! && !(autoload && *p == AUTOLOAD_CHAR)) { semsg(_(e_illvar), varname); return FALSE; *** ../vim-8.2.2161/src/proto/evalvars.pro 2020-12-12 14:33:37.096920916 +0100 --- src/proto/evalvars.pro 2020-12-19 16:20:48.425750518 +0100 *************** *** 75,81 **** int var_check_fixed(int flags, char_u *name, int use_gettext); int var_wrong_func_name(char_u *name, int new_var); int value_check_lock(int lock, char_u *name, int use_gettext); ! int valid_varname(char_u *varname); void reset_v_option_vars(void); void assert_error(garray_T *gap); int var_exists(char_u *var); --- 75,81 ---- int var_check_fixed(int flags, char_u *name, int use_gettext); int var_wrong_func_name(char_u *name, int new_var); int value_check_lock(int lock, char_u *name, int use_gettext); ! int valid_varname(char_u *varname, int autoload); void reset_v_option_vars(void); void assert_error(garray_T *gap); int var_exists(char_u *var); *** ../vim-8.2.2161/src/testdir/test_vim9_disassemble.vim 2020-12-13 14:19:22.131979168 +0100 --- src/testdir/test_vim9_disassemble.vim 2020-12-19 15:48:11.699601520 +0100 *************** *** 23,28 **** --- 23,29 ---- echo s:scriptvar echo g:globalvar echo get(g:, "global") + echo g:auto#var echo b:buffervar echo get(b:, "buffer") echo w:windowvar *************** *** 68,75 **** 'echo get(g:, "global")\_s*' .. '\d\+ LOAD g:\_s*' .. '\d\+ PUSHS "global"\_s*' .. ! '\d\+ BCALL get(argc 2).*' .. ! ' LOADB b:buffervar.*' .. 'echo get(b:, "buffer")\_s*' .. '\d\+ LOAD b:\_s*' .. '\d\+ PUSHS "buffer"\_s*' .. --- 69,82 ---- 'echo get(g:, "global")\_s*' .. '\d\+ LOAD g:\_s*' .. '\d\+ PUSHS "global"\_s*' .. ! '\d\+ BCALL get(argc 2)\_s*' .. ! '\d\+ ECHO 1\_s*' .. ! 'echo g:auto#var\_s*' .. ! '\d\+ LOADAUTO g:auto#var\_s*' .. ! '\d\+ ECHO 1\_s*' .. ! 'echo b:buffervar\_s*' .. ! '\d\+ LOADB b:buffervar\_s*' .. ! '\d\+ ECHO 1\_s*' .. 'echo get(b:, "buffer")\_s*' .. '\d\+ LOAD b:\_s*' .. '\d\+ PUSHS "buffer"\_s*' .. *************** *** 197,202 **** --- 204,210 ---- v:char = 'abc' s:scriptvar = 'sv' g:globalvar = 'gv' + g:auto#var = 'av' b:buffervar = 'bv' w:windowvar = 'wv' t:tabpagevar = 'tv' *************** *** 220,225 **** --- 228,235 ---- ' STORES s:scriptvar in .*test_vim9_disassemble.vim.*' .. 'g:globalvar = ''gv''.*' .. ' STOREG g:globalvar.*' .. + 'g:auto#var = ''av''.*' .. + ' STOREAUTO g:auto#var.*' .. 'b:buffervar = ''bv''.*' .. ' STOREB b:buffervar.*' .. 'w:windowvar = ''wv''.*' .. *** ../vim-8.2.2161/src/testdir/test_vim9_script.vim 2020-12-14 18:31:24.062840347 +0100 --- src/testdir/test_vim9_script.vim 2020-12-19 16:27:46.256385358 +0100 *************** *** 2779,2788 **** quit enddef ! " test using a vim9script that is auto-loaded from an autocmd def Test_vim9_autoload() var lines =<< trim END vim9script def foo#test() echomsg getreg('"') enddef --- 2779,2812 ---- quit enddef ! " test using an auto-loaded function and variable def Test_vim9_autoload() var lines =<< trim END vim9script + def some#gettest(): string + return 'test' + enddef + g:some#name = 'name' + END + + mkdir('Xdir/autoload', 'p') + writefile(lines, 'Xdir/autoload/some.vim') + var save_rtp = &rtp + exe 'set rtp^=' .. getcwd() .. '/Xdir' + + assert_equal('test', g:some#gettest()) + assert_equal('name', g:some#name) + g:some#other = 'other' + assert_equal('other', g:some#other) + + delete('Xdir', 'rf') + &rtp = save_rtp + enddef + + " test using a vim9script that is auto-loaded from an autocmd + def Test_vim9_aucmd_autoload() + var lines =<< trim END + vim9script def foo#test() echomsg getreg('"') enddef *************** *** 2842,2847 **** --- 2866,2877 ---- delete('Xdidit') delete('Xscript') delete('Xruntime', 'rf') + + lines =<< trim END + vim9script + var foo#bar = 'asdf' + END + CheckScriptFailure(lines, 'E461: Illegal variable name: foo#bar', 2) enddef def Test_script_var_in_autocmd() *** ../vim-8.2.2161/src/version.c 2020-12-19 13:32:01.960764077 +0100 --- src/version.c 2020-12-19 16:29:38.512012925 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2162, /**/ -- If you had to identify, in one word, the reason why the human race has not achieved, and never will achieve, its full potential, that word would be "meetings." /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///