diff src/vim9compile.c @ 20091:a64c16ff98b8 v8.2.0601

patch 8.2.0601: Vim9: :unlet is not compiled Commit: https://github.com/vim/vim/commit/d72c1bf0a6784afdc8d8ceab4a007cd76d5b81e1 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Apr 19 16:28:59 2020 +0200 patch 8.2.0601: Vim9: :unlet is not compiled Problem: Vim9: :unlet is not compiled. Solution: Implement :unlet instruction and check for errors.
author Bram Moolenaar <Bram@vim.org>
date Sun, 19 Apr 2020 16:30:04 +0200
parents 7fc5d62fe2a5
children 058b41f85bcb
line wrap: on
line diff
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -987,6 +987,23 @@ generate_LOADV(
 }
 
 /*
+ * Generate an ISN_UNLET instruction.
+ */
+    static int
+generate_UNLET(cctx_T *cctx, char_u *name, int forceit)
+{
+    isn_T	*isn;
+
+    RETURN_OK_IF_SKIP(cctx);
+    if ((isn = generate_instr(cctx, ISN_UNLET)) == NULL)
+	return FAIL;
+    isn->isn_arg.unlet.ul_name = vim_strsave(name);
+    isn->isn_arg.unlet.ul_forceit = forceit;
+
+    return OK;
+}
+
+/*
  * Generate an ISN_LOADS instruction.
  */
     static int
@@ -4543,6 +4560,81 @@ theend:
 }
 
 /*
+ * Check if "name" can be "unlet".
+ */
+    int
+check_vim9_unlet(char_u *name)
+{
+    if (name[1] != ':' || vim_strchr((char_u *)"gwtb", *name) == NULL)
+    {
+	semsg(_("E1081: Cannot unlet %s"), name);
+	return FAIL;
+    }
+    return OK;
+}
+
+/*
+ * Callback passed to ex_unletlock().
+ */
+    static int
+compile_unlet(
+    lval_T  *lvp,
+    char_u  *name_end,
+    exarg_T *eap,
+    int	    deep UNUSED,
+    void    *coookie)
+{
+    cctx_T *cctx = coookie;
+
+    if (lvp->ll_tv == NULL)
+    {
+	char_u	*p = lvp->ll_name;
+	int	cc = *name_end;
+	int	ret = OK;
+
+	// Normal name.  Only supports g:, w:, t: and b: namespaces.
+	*name_end = NUL;
+	if (check_vim9_unlet(p) == FAIL)
+	    ret = FAIL;
+	else
+	    ret = generate_UNLET(cctx, p, eap->forceit);
+
+	*name_end = cc;
+	return ret;
+    }
+
+    // TODO: unlet {list}[idx]
+    // TODO: unlet {dict}[key]
+    emsg("Sorry, :unlet not fully implemented yet");
+    return FAIL;
+}
+
+/*
+ * compile "unlet var", "lock var" and "unlock var"
+ * "arg" points to "var".
+ */
+    static char_u *
+compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
+{
+    char_u *p = arg;
+
+    if (eap->cmdidx != CMD_unlet)
+    {
+	emsg("Sorry, :lock and unlock not implemented yet");
+	return NULL;
+    }
+
+    if (*p == '!')
+    {
+	p = skipwhite(p + 1);
+	eap->forceit = TRUE;
+    }
+
+    ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
+    return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
+}
+
+/*
  * Compile an :import command.
  */
     static char_u *
@@ -6031,6 +6123,12 @@ compile_def_function(ufunc_T *ufunc, int
 		    line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
 		    break;
 
+	    case CMD_unlet:
+	    case CMD_unlockvar:
+	    case CMD_lockvar:
+		    line = compile_unletlock(p, &ea, &cctx);
+		    break;
+
 	    case CMD_import:
 		    line = compile_import(p, &cctx);
 		    break;
@@ -6264,6 +6362,10 @@ delete_instr(isn_T *isn)
 	    vim_free(isn->isn_arg.loadstore.ls_name);
 	    break;
 
+	case ISN_UNLET:
+	    vim_free(isn->isn_arg.unlet.ul_name);
+	    break;
+
 	case ISN_STOREOPT:
 	    vim_free(isn->isn_arg.storeopt.so_name);
 	    break;