Patch 8.2.3339
Problem: Vim9: cannot lock a member in a local dict.
Solution: Get the local dict from the stack and pass it to get_lval().
Files: src/eval.c, src/vim9execute.c, src/vim9compile.c, src/vim9.h,
src/globals.h, src/testdir/test_vim9_cmd.vim,
src/testdir/test_vim9_disassemble.vim
*** ../vim-8.2.3338/src/eval.c 2021-08-11 21:49:19.626869328 +0200
--- src/eval.c 2021-08-13 18:58:32.241535354 +0200
***************
*** 902,918 ****
if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
return p;
! cc = *p;
! *p = NUL;
! // When we would write to the variable pass &ht and prevent autoload.
! writing = !(flags & GLV_READ_ONLY);
! v = find_var(lp->ll_name, writing ? &ht : NULL,
(flags & GLV_NO_AUTOLOAD) || writing);
! if (v == NULL && !quiet)
! semsg(_(e_undefined_variable_str), lp->ll_name);
! *p = cc;
! if (v == NULL)
! return NULL;
if (in_vim9script() && (flags & GLV_NO_DECL) == 0)
{
--- 902,927 ----
if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
return p;
! if (in_vim9script() && lval_root != NULL)
! {
! // using local variable
! lp->ll_tv = lval_root;
! }
! else
! {
! cc = *p;
! *p = NUL;
! // When we would write to the variable pass &ht and prevent autoload.
! writing = !(flags & GLV_READ_ONLY);
! v = find_var(lp->ll_name, writing ? &ht : NULL,
(flags & GLV_NO_AUTOLOAD) || writing);
! if (v == NULL && !quiet)
! semsg(_(e_undefined_variable_str), lp->ll_name);
! *p = cc;
! if (v == NULL)
! return NULL;
! lp->ll_tv = &v->di_tv;
! }
if (in_vim9script() && (flags & GLV_NO_DECL) == 0)
{
***************
*** 924,930 ****
/*
* Loop until no more [idx] or .key is following.
*/
- lp->ll_tv = &v->di_tv;
var1.v_type = VAR_UNKNOWN;
var2.v_type = VAR_UNKNOWN;
while (*p == '[' || (*p == '.' && p[1] != '=' && p[1] != '.'))
--- 933,938 ----
*** ../vim-8.2.3338/src/vim9execute.c 2021-08-11 21:49:19.626869328 +0200
--- src/vim9execute.c 2021-08-13 19:25:54.238568203 +0200
***************
*** 1396,1401 ****
--- 1396,1422 ----
return OK;
}
+ /*
+ * Execute iptr->isn_arg.string as an Ex command.
+ */
+ static int
+ exec_command(isn_T *iptr)
+ {
+ source_cookie_T cookie;
+
+ SOURCING_LNUM = iptr->isn_lnum;
+ // Pass getsourceline to get an error for a missing ":end"
+ // command.
+ CLEAR_FIELD(cookie);
+ cookie.sourcing_lnum = iptr->isn_lnum - 1;
+ if (do_cmdline(iptr->isn_arg.string,
+ getsourceline, &cookie,
+ DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED) == FAIL
+ || did_emsg)
+ return FAIL;
+ return OK;
+ }
+
// used for v_instr of typval of VAR_INSTR
struct instr_S {
ectx_T *instr_ectx;
***************
*** 1637,1657 ****
{
// execute Ex command line
case ISN_EXEC:
! {
! source_cookie_T cookie;
!
! SOURCING_LNUM = iptr->isn_lnum;
! // Pass getsourceline to get an error for a missing ":end"
! // command.
! CLEAR_FIELD(cookie);
! cookie.sourcing_lnum = iptr->isn_lnum - 1;
! if (do_cmdline(iptr->isn_arg.string,
! getsourceline, &cookie,
! DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED)
! == FAIL
! || did_emsg)
! goto on_error;
! }
break;
// execute Ex command line split at NL characters.
--- 1658,1665 ----
{
// execute Ex command line
case ISN_EXEC:
! if (exec_command(iptr) == FAIL)
! goto on_error;
break;
// execute Ex command line split at NL characters.
***************
*** 2880,2885 ****
--- 2888,2910 ----
vim_unsetenv(iptr->isn_arg.unlet.ul_name);
break;
+ case ISN_LOCKUNLOCK:
+ {
+ typval_T *lval_root_save = lval_root;
+ int res;
+
+ // Stack has the local variable, argument the whole :lock
+ // or :unlock command, like ISN_EXEC.
+ --ectx->ec_stack.ga_len;
+ lval_root = STACK_TV_BOT(0);
+ res = exec_command(iptr);
+ clear_tv(lval_root);
+ lval_root = lval_root_save;
+ if (res == FAIL)
+ goto on_error;
+ }
+ break;
+
case ISN_LOCKCONST:
item_lock(STACK_TV_BOT(-1), 100, TRUE, TRUE);
break;
***************
*** 5244,5249 ****
--- 5269,5277 ----
case ISN_UNLETRANGE:
smsg("%s%4d UNLETRANGE", pfx, current);
break;
+ case ISN_LOCKUNLOCK:
+ smsg("%s%4d LOCKUNLOCK %s", pfx, current, iptr->isn_arg.string);
+ break;
case ISN_LOCKCONST:
smsg("%s%4d LOCKCONST", pfx, current);
break;
*** ../vim-8.2.3338/src/vim9compile.c 2021-08-12 17:06:01.392925681 +0200
--- src/vim9compile.c 2021-08-13 19:26:07.514548558 +0200
***************
*** 2262,2273 ****
}
static int
! generate_EXEC(cctx_T *cctx, char_u *line)
{
isn_T *isn;
RETURN_OK_IF_SKIP(cctx);
! if ((isn = generate_instr(cctx, ISN_EXEC)) == NULL)
return FAIL;
isn->isn_arg.string = vim_strsave(line);
return OK;
--- 2262,2273 ----
}
static int
! generate_EXEC(cctx_T *cctx, isntype_T isntype, char_u *line)
{
isn_T *isn;
RETURN_OK_IF_SKIP(cctx);
! if ((isn = generate_instr(cctx, isntype)) == NULL)
return FAIL;
isn->isn_arg.string = vim_strsave(line);
return OK;
***************
*** 7426,7431 ****
--- 7426,7432 ----
int ret = OK;
size_t len;
char_u *buf;
+ isntype_T isn = ISN_EXEC;
if (cctx->ctx_skip == SKIP_YES)
return OK;
***************
*** 7437,7444 ****
if (lookup_local(p, end - p, NULL, cctx) == OK)
{
! emsg(_(e_cannot_lock_unlock_local_variable));
! return FAIL;
}
}
--- 7438,7456 ----
if (lookup_local(p, end - p, NULL, cctx) == OK)
{
! char_u *s = p;
!
! if (*end != '.' && *end != '[')
! {
! emsg(_(e_cannot_lock_unlock_local_variable));
! return FAIL;
! }
!
! // For "d.member" put the local variable on the stack, it will be
! // passed to ex_lockvar() indirectly.
! if (compile_load(&s, end, cctx, FALSE, FALSE) == FAIL)
! return FAIL;
! isn = ISN_LOCKUNLOCK;
}
}
***************
*** 7453,7459 ****
vim_snprintf((char *)buf, len, "%s %s",
eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar",
p);
! ret = generate_EXEC(cctx, buf);
vim_free(buf);
*name_end = cc;
--- 7465,7471 ----
vim_snprintf((char *)buf, len, "%s %s",
eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar",
p);
! ret = generate_EXEC(cctx, isn, buf);
vim_free(buf);
*name_end = cc;
***************
*** 9110,9116 ****
generate_EXECCONCAT(cctx, count);
}
else
! generate_EXEC(cctx, line);
theend:
if (*nextcmd != NUL)
--- 9122,9128 ----
generate_EXECCONCAT(cctx, count);
}
else
! generate_EXEC(cctx, ISN_EXEC, line);
theend:
if (*nextcmd != NUL)
***************
*** 10198,10203 ****
--- 10210,10216 ----
case ISN_LOADOPT:
case ISN_LOADT:
case ISN_LOADW:
+ case ISN_LOCKUNLOCK:
case ISN_PUSHEXC:
case ISN_PUSHFUNC:
case ISN_PUSHS:
*** ../vim-8.2.3338/src/vim9.h 2021-08-07 15:05:44.707105779 +0200
--- src/vim9.h 2021-08-13 19:09:32.924125204 +0200
***************
*** 70,75 ****
--- 70,76 ----
ISN_UNLETINDEX, // unlet item of list or dict
ISN_UNLETRANGE, // unlet items of list
+ ISN_LOCKUNLOCK, // :lock and :unlock for local variable member
ISN_LOCKCONST, // lock constant value
// constants
*** ../vim-8.2.3338/src/globals.h 2021-07-28 16:51:49.857364325 +0200
--- src/globals.h 2021-08-13 19:19:12.567060140 +0200
***************
*** 1835,1840 ****
--- 1835,1842 ----
#endif
#ifdef FEAT_EVAL
EXTERN int input_busy INIT(= 0); // when inside get_user_input() then > 0
+
+ EXTERN typval_T *lval_root INIT(= NULL);
#endif
#ifdef FEAT_BEVAL_TERM
*** ../vim-8.2.3338/src/testdir/test_vim9_cmd.vim 2021-08-10
19:52:57.474235537 +0200
--- src/testdir/test_vim9_cmd.vim 2021-08-13 19:32:12.881957940 +0200
***************
*** 1195,1200 ****
--- 1195,1217 ----
s:theList[1] = 44
assert_equal([1, 44, 3], s:theList)
+ var d = {a: 1, b: 2}
+ d.a = 3
+ d.b = 4
+ assert_equal({a: 3, b: 4}, d)
+ lockvar d.a
+ d.b = 5
+ var ex = ''
+ try
+ d.a = 6
+ catch
+ ex = v:exception
+ endtry
+ assert_match('E1121:', ex)
+ unlockvar d.a
+ d.a = 7
+ assert_equal({a: 7, b: 5}, d)
+
var lines =<< trim END
vim9script
var theList = [1, 2, 3]
*** ../vim-8.2.3338/src/testdir/test_vim9_disassemble.vim 2021-08-10
22:51:59.369449616 +0200
--- src/testdir/test_vim9_disassemble.vim 2021-08-13 19:39:26.217179419
+0200
***************
*** 588,593 ****
--- 588,612 ----
res)
enddef
+ def s:LockLocal()
+ var d = {a: 1}
+ lockvar d.a
+ enddef
+
+ def Test_disassemble_locl_local()
+ var res = execute('disass s:LockLocal')
+ assert_match('<SNR>\d*_LockLocal\_s*' ..
+ 'var d = {a: 1}\_s*' ..
+ '\d PUSHS "a"\_s*' ..
+ '\d PUSHNR 1\_s*' ..
+ '\d NEWDICT size 1\_s*' ..
+ '\d STORE $0\_s*' ..
+ 'lockvar d.a\_s*' ..
+ '\d LOAD $0\_s*' ..
+ '\d LOCKUNLOCK lockvar d.a\_s*',
+ res)
+ enddef
+
def s:ScriptFuncTry()
try
echo "yes"
*** ../vim-8.2.3338/src/version.c 2021-08-13 18:19:54.678450486 +0200
--- src/version.c 2021-08-13 19:08:31.736257971 +0200
***************
*** 757,758 ****
--- 757,760 ----
{ /* Add new patch number below this line */
+ /**/
+ 3339,
/**/
--
TIM: But follow only if you are men of valour. For the entrance to this cave
is guarded by a monster, a creature so foul and cruel that no man yet has
fought with it and lived. Bones of full fifty men lie strewn about its
lair ...
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202108131741.17DHfIJv3545478%40masaka.moolenaar.net.