summaryrefslogtreecommitdiffstats
path: root/src/vim9cmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vim9cmds.c')
-rw-r--r--src/vim9cmds.c81
1 files changed, 70 insertions, 11 deletions
diff --git a/src/vim9cmds.c b/src/vim9cmds.c
index 0ca3be11a8..0d6dc01f9f 100644
--- a/src/vim9cmds.c
+++ b/src/vim9cmds.c
@@ -189,10 +189,15 @@ compile_lock_unlock(
int cc = *name_end;
char_u *p = lvp->ll_name;
int ret = OK;
- size_t len;
char_u *buf;
isntype_T isn = ISN_EXEC;
char *cmd = eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar";
+ int is_arg = FALSE;
+
+#ifdef LOG_LOCKVAR
+ ch_log(NULL, "LKVAR: compile_lock_unlock(): cookie %p, name %s",
+ coookie, p);
+#endif
if (cctx->ctx_skip == SKIP_YES)
return OK;
@@ -207,20 +212,68 @@ compile_lock_unlock(
if (p[1] != ':')
{
char_u *end = find_name_end(p, NULL, NULL, FNE_CHECK_START);
+ // If name is is locally accessible, except for local var,
+ // then put it on the stack to use with ISN_LOCKUNLOCK.
+ // This could be v.memb, v[idx_key]; bare class variable,
+ // function arg. The local variable on the stack, will be passed
+ // to ex_lockvar() indirectly.
- if (lookup_local(p, end - p, NULL, cctx) == OK)
- {
- char_u *s = p;
+ char_u *name = NULL;
+ int len = end - p;
- if (*end != '.' && *end != '[')
+ if (lookup_local(p, len, NULL, cctx) == OK)
+ {
+ // Handle "this", "this.val", "anyvar[idx]"
+ if (*end != '.' && *end != '['
+ && (len != 4 || STRNCMP("this", p, len) != 0))
{
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)
+ // Push the local on the stack, could be "this".
+ name = p;
+#ifdef LOG_LOCKVAR
+ ch_log(NULL, "LKVAR: compile... lookup_local: name %s", name);
+#endif
+ }
+ if (name == NULL)
+ {
+ class_T *cl;
+ if (cctx_class_member_idx(cctx, p, len, &cl) >= 0)
+ {
+ if (*end != '.' && *end != '[')
+ {
+ // Push the class of the bare class variable name
+ name = cl->class_name;
+ len = STRLEN(name);
+#ifdef LOG_LOCKVAR
+ ch_log(NULL, "LKVAR: compile... cctx_class_member: name %s",
+ name);
+#endif
+ }
+ }
+ }
+ if (name == NULL)
+ {
+ int idx;
+ type_T *type;
+ // Can lockvar any function arg.
+ // TODO: test arg[idx]/arg.member
+ if (arg_exists(p, len, &idx, &type, NULL, cctx) == OK)
+ {
+ name = p;
+ is_arg = TRUE;
+#ifdef LOG_LOCKVAR
+ ch_log(NULL, "LKVAR: compile... arg_exists: name %s", name);
+#endif
+ }
+ }
+ if (name != NULL)
+ {
+#ifdef LOG_LOCKVAR
+ ch_log(NULL, "LKVAR: compile... INS_LOCKUNLOCK %s", name);
+#endif
+ if (compile_load(&name, name + len, cctx, FALSE, FALSE) == FAIL)
return FAIL;
isn = ISN_LOCKUNLOCK;
}
@@ -228,7 +281,7 @@ compile_lock_unlock(
// Checking is done at runtime.
*name_end = NUL;
- len = name_end - p + 20;
+ size_t len = name_end - p + 20;
buf = alloc(len);
if (buf == NULL)
ret = FAIL;
@@ -238,7 +291,13 @@ compile_lock_unlock(
vim_snprintf((char *)buf, len, "%s! %s", cmd, p);
else
vim_snprintf((char *)buf, len, "%s %d %s", cmd, deep, p);
- ret = generate_EXEC_copy(cctx, isn, buf);
+#ifdef LOG_LOCKVAR
+ ch_log(NULL, "LKVAR: compile... buf %s", buf);
+#endif
+ if (isn == ISN_LOCKUNLOCK)
+ ret = generate_LOCKUNLOCK(cctx, buf, is_arg);
+ else
+ ret = generate_EXEC_copy(cctx, isn, buf);
vim_free(buf);
*name_end = cc;