To: vim_dev@googlegroups.com Subject: Patch 8.2.0600 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0600 Problem: Vim9: cannot read or write w:, t: and b: variables. Solution: Implement load and store for w:, t: and b: variables. (closes #5950) Files: src/testdir/test_vim9_disassemble.vim, src/testdir/test_vim9_expr.vim, src/testdir/test_vim9_script.vim, src/vim9.h, src/vim9compile.c, src/vim9execute.c *** ../vim-8.2.0599/src/testdir/test_vim9_disassemble.vim 2020-04-18 19:53:24.535912281 +0200 --- src/testdir/test_vim9_disassemble.vim 2020-04-19 14:19:23.685767255 +0200 *************** *** 8,13 **** --- 8,16 ---- let s:scriptvar = 4 let g:globalvar = 'g' + let b:buffervar = 'b' + let w:windowvar = 'w' + let t:tabpagevar = 't' def s:ScriptFuncLoad(arg: string) let local = 1 *************** *** 17,22 **** --- 20,28 ---- echo v:version echo s:scriptvar echo g:globalvar + echo b:buffervar + echo w:windowvar + echo t:tabpagevar echo &tabstop echo $ENVVAR echo @z *************** *** 39,44 **** --- 45,53 ---- ' LOADV v:version.*' .. ' LOADS s:scriptvar from .*test_vim9_disassemble.vim.*' .. ' LOADG g:globalvar.*' .. + ' LOADB b:buffervar.*' .. + ' LOADW w:windowvar.*' .. + ' LOADT t:tabpagevar.*' .. ' LOADENV $ENVVAR.*' .. ' LOADREG @z.*', res) *************** *** 79,84 **** --- 88,96 ---- v:char = 'abc' s:scriptvar = 'sv' g:globalvar = 'gv' + b:buffervar = 'bv' + w:windowvar = 'wv' + t:tabpagevar = 'tv' &tabstop = 8 $ENVVAR = 'ev' @z = 'rv' *************** *** 99,104 **** --- 111,122 ---- ' STORES s:scriptvar in .*test_vim9_disassemble.vim.*' .. 'g:globalvar = ''gv''.*' .. ' STOREG g:globalvar.*' .. + 'b:buffervar = ''bv''.*' .. + ' STOREB b:buffervar.*' .. + 'w:windowvar = ''wv''.*' .. + ' STOREW w:windowvar.*' .. + 't:tabpagevar = ''tv''.*' .. + ' STORET t:tabpagevar.*' .. '&tabstop = 8.*' .. ' STOREOPT &tabstop.*' .. '$ENVVAR = ''ev''.*' .. *** ../vim-8.2.0599/src/testdir/test_vim9_expr.vim 2020-04-13 17:20:56.174130307 +0200 --- src/testdir/test_vim9_expr.vim 2020-04-19 14:19:23.685767255 +0200 *************** *** 931,941 **** call CheckDefFailure("echo l:somevar", 'E1075:') call CheckDefFailure("echo x:somevar", 'E1075:') - " TODO - call CheckDefFailure("echo b:somevar", 'not supported yet') - call CheckDefFailure("echo w:somevar", 'not supported yet') - call CheckDefFailure("echo t:somevar", 'not supported yet') - call CheckDefExecFailure("let x = +g:astring", 'E1030:') call CheckDefExecFailure("let x = +g:ablob", 'E974:') call CheckDefExecFailure("let x = +g:alist", 'E745:') --- 931,936 ---- *** ../vim-8.2.0599/src/testdir/test_vim9_script.vim 2020-04-18 19:53:24.535912281 +0200 --- src/testdir/test_vim9_script.vim 2020-04-19 14:30:18.184264079 +0200 *************** *** 135,140 **** --- 135,172 ---- call CheckDefFailure(['v:errmsg += 123'], 'E1013:') enddef + def Test_assignment_local() + " Test in a separated file in order not to the current buffer/window/tab is + " changed. + let script_lines: list =<< trim END + let b:existing = 'yes' + let w:existing = 'yes' + let t:existing = 'yes' + + def Test_assignment_local_internal() + b:newvar = 'new' + assert_equal('new', b:newvar) + assert_equal('yes', b:existing) + b:existing = 'no' + assert_equal('no', b:existing) + + w:newvar = 'new' + assert_equal('new', w:newvar) + assert_equal('yes', w:existing) + w:existing = 'no' + assert_equal('no', w:existing) + + t:newvar = 'new' + assert_equal('new', t:newvar) + assert_equal('yes', t:existing) + t:existing = 'no' + assert_equal('no', t:existing) + enddef + call Test_assignment_local_internal() + END + call CheckScriptSuccess(script_lines) + enddef + def Test_assignment_default() # Test default values. *************** *** 201,211 **** --- 233,249 ---- call CheckDefFailure(['let @a = 5'], 'E1066:') call CheckDefFailure(['let g:var = 5'], 'E1016:') + call CheckDefFailure(['let w:var = 5'], 'E1079:') + call CheckDefFailure(['let b:var = 5'], 'E1078:') + call CheckDefFailure(['let t:var = 5'], 'E1080:') call CheckDefFailure(['let anr = 4', 'anr ..= "text"'], 'E1019:') call CheckDefFailure(['let xnr += 4'], 'E1020:') call CheckScriptFailure(['vim9script', 'def Func()', 'let dummy = s:notfound', 'enddef'], 'E1050:') + " TODO: implement this error + "call CheckScriptFailure(['vim9script', 'let svar = 123', 'unlet svar'], 'E1050:') + "call CheckScriptFailure(['vim9script', 'let svar = 123', 'unlet s:svar'], 'E1050:') call CheckDefFailure(['let var: list = [123]'], 'expected list but got list') call CheckDefFailure(['let var: list = ["xx"]'], 'expected list but got list') *** ../vim-8.2.0599/src/vim9.h 2020-04-09 21:08:06.298505479 +0200 --- src/vim9.h 2020-04-19 14:19:23.685767255 +0200 *************** *** 20,25 **** --- 20,28 ---- 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_LOADB, // push b: variable isn_arg.string + ISN_LOADW, // push w: variable isn_arg.string + ISN_LOADT, // push t: variable isn_arg.string ISN_LOADS, // push s: variable isn_arg.loadstore ISN_LOADSCRIPT, // push script-local variable isn_arg.script. ISN_LOADOPT, // push option isn_arg.string *************** *** 29,34 **** --- 32,40 ---- 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_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 ISN_STORES, // pop into script variable isn_arg.loadstore ISN_STORESCRIPT, // pop into script variable isn_arg.script ISN_STOREOPT, // pop into option isn_arg.string *** ../vim-8.2.0599/src/vim9compile.c 2020-04-18 19:53:24.531912284 +0200 --- src/vim9compile.c 2020-04-19 14:19:23.685767255 +0200 *************** *** 2235,2252 **** } else if (**arg == 'b') { ! semsg("Namespace b: not supported yet: %s", *arg); ! goto theend; } else if (**arg == 'w') { ! semsg("Namespace w: not supported yet: %s", *arg); ! goto theend; } else if (**arg == 't') { ! semsg("Namespace t: not supported yet: %s", *arg); ! goto theend; } else { --- 2235,2255 ---- } else if (**arg == 'b') { ! // Buffer-local variables can be defined later, thus we don't check ! // if it exists, give error at runtime. ! res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any); } else if (**arg == 'w') { ! // Window-local variables can be defined later, thus we don't check ! // if it exists, give error at runtime. ! res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any); } else if (**arg == 't') { ! // Tabpage-local variables can be defined later, thus we don't ! // check if it exists, give error at runtime. ! res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any); } else { *************** *** 3958,3963 **** --- 3961,3969 ---- dest_option, dest_env, dest_global, + dest_buffer, + dest_window, + dest_tab, dest_vimvar, dest_script, dest_reg, *************** *** 4087,4092 **** --- 4093,4125 ---- goto theend; } } + else if (STRNCMP(arg, "b:", 2) == 0) + { + dest = dest_buffer; + if (is_decl) + { + semsg(_("E1078: Cannot declare a buffer variable: %s"), name); + goto theend; + } + } + else if (STRNCMP(arg, "w:", 2) == 0) + { + dest = dest_window; + if (is_decl) + { + semsg(_("E1079: Cannot declare a window variable: %s"), name); + goto theend; + } + } + else if (STRNCMP(arg, "t:", 2) == 0) + { + dest = dest_tab; + if (is_decl) + { + semsg(_("E1080: Cannot declare a tab variable: %s"), name); + goto theend; + } + } else if (STRNCMP(arg, "v:", 2) == 0) { typval_T *vtv; *************** *** 4245,4250 **** --- 4278,4292 ---- 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); + break; + case dest_window: + generate_LOAD(cctx, ISN_LOADW, 0, name + 2, type); + break; + case dest_tab: + generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type); + break; case dest_script: compile_load_scriptvar(cctx, name + (name[1] == ':' ? 2 : 0), NULL, NULL, TRUE); *************** *** 4410,4415 **** --- 4452,4469 ---- // include g: with the name, easier to execute that way generate_STORE(cctx, ISN_STOREG, 0, name); break; + case dest_buffer: + // include b: with the name, easier to execute that way + generate_STORE(cctx, ISN_STOREB, 0, name); + break; + case dest_window: + // include w: with the name, easier to execute that way + generate_STORE(cctx, ISN_STOREW, 0, name); + break; + case dest_tab: + // include t: with the name, easier to execute that way + generate_STORE(cctx, ISN_STORET, 0, name); + break; case dest_env: generate_STORE(cctx, ISN_STOREENV, 0, name + 1); break; *************** *** 6189,6200 **** --- 6243,6260 ---- case ISN_EXEC: case ISN_LOADENV: case ISN_LOADG: + case ISN_LOADB: + case ISN_LOADW: + case ISN_LOADT: case ISN_LOADOPT: case ISN_MEMBER: case ISN_PUSHEXC: case ISN_PUSHS: case ISN_STOREENV: case ISN_STOREG: + case ISN_STOREB: + case ISN_STOREW: + case ISN_STORET: case ISN_PUSHFUNC: vim_free(isn->isn_arg.string); break; *** ../vim-8.2.0599/src/vim9execute.c 2020-04-18 19:53:24.531912284 +0200 --- src/vim9execute.c 2020-04-19 14:19:23.685767255 +0200 *************** *** 446,451 **** --- 446,452 ---- restore_funccal(); } + /* * Execute a function by "name". * This can be a builtin function, user function or a funcref. *************** *** 757,772 **** } break; ! // load g: variable case ISN_LOADG: ! { ! dictitem_T *di = find_var_in_ht(get_globvar_ht(), 0, ! iptr->isn_arg.string, TRUE); if (di == NULL) { ! semsg(_("E121: Undefined variable: g:%s"), ! iptr->isn_arg.string); goto failed; } else --- 758,799 ---- } break; ! // load g:/b:/w:/t: variable case ISN_LOADG: ! case ISN_LOADB: ! case ISN_LOADW: ! case ISN_LOADT: ! { ! dictitem_T *di = NULL; ! hashtab_T *ht = NULL; ! char namespace; ! switch (iptr->isn_type) ! { ! case ISN_LOADG: ! ht = get_globvar_ht(); ! namespace = 'g'; ! break; ! case ISN_LOADB: ! ht = &curbuf->b_vars->dv_hashtab; ! namespace = 'b'; ! break; ! case ISN_LOADW: ! ht = &curwin->w_vars->dv_hashtab; ! namespace = 'w'; ! break; ! case ISN_LOADT: ! ht = &curtab->tp_vars->dv_hashtab; ! namespace = 't'; ! break; ! default: // Cannot reach here ! goto failed; ! } ! di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE); if (di == NULL) { ! semsg(_("E121: Undefined variable: %c:%s"), ! namespace, iptr->isn_arg.string); goto failed; } else *************** *** 925,937 **** goto failed; break; ! // store g: variable case ISN_STOREG: { dictitem_T *di; --ectx.ec_stack.ga_len; ! di = find_var_in_ht(get_globvar_ht(), 0, iptr->isn_arg.string + 2, TRUE); if (di == NULL) store_var(iptr->isn_arg.string, STACK_TV_BOT(0)); --- 952,985 ---- goto failed; break; ! // store g:/b:/w:/t: variable case ISN_STOREG: + case ISN_STOREB: + case ISN_STOREW: + case ISN_STORET: { dictitem_T *di; + hashtab_T *ht; + switch (iptr->isn_type) + { + case ISN_STOREG: + ht = get_globvar_ht(); + break; + case ISN_STOREB: + ht = &curbuf->b_vars->dv_hashtab; + break; + case ISN_STOREW: + ht = &curwin->w_vars->dv_hashtab; + break; + case ISN_STORET: + ht = &curtab->tp_vars->dv_hashtab; + break; + default: // Cannot reach here + goto failed; + } --ectx.ec_stack.ga_len; ! di = find_var_in_ht(ht, 0, iptr->isn_arg.string + 2, TRUE); if (di == NULL) store_var(iptr->isn_arg.string, STACK_TV_BOT(0)); *************** *** 1918,1923 **** --- 1966,1980 ---- case ISN_LOADG: smsg("%4d LOADG g:%s", current, iptr->isn_arg.string); break; + case ISN_LOADB: + smsg("%4d LOADB b:%s", current, iptr->isn_arg.string); + break; + case ISN_LOADW: + smsg("%4d LOADW w:%s", current, iptr->isn_arg.string); + break; + case ISN_LOADT: + smsg("%4d LOADT t:%s", current, iptr->isn_arg.string); + break; case ISN_LOADOPT: smsg("%4d LOADOPT %s", current, iptr->isn_arg.string); break; *************** *** 1943,1948 **** --- 2000,2014 ---- case ISN_STOREG: smsg("%4d STOREG %s", current, iptr->isn_arg.string); break; + case ISN_STOREB: + smsg("%4d STOREB %s", current, iptr->isn_arg.string); + break; + case ISN_STOREW: + smsg("%4d STOREW %s", current, iptr->isn_arg.string); + break; + case ISN_STORET: + smsg("%4d STORET %s", current, iptr->isn_arg.string); + break; case ISN_STORES: { scriptitem_T *si = SCRIPT_ITEM( *** ../vim-8.2.0599/src/version.c 2020-04-19 14:02:22.427687032 +0200 --- src/version.c 2020-04-19 14:21:27.801488599 +0200 *************** *** 748,749 **** --- 748,751 ---- { /* Add new patch number below this line */ + /**/ + 600, /**/ -- The only way the average employee can speak to an executive is by taking a second job as a golf caddie. (Scott Adams - The Dilbert principle) /// 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 ///