summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-11-22 18:15:44 +0100
committerBram Moolenaar <Bram@vim.org>2020-11-22 18:15:44 +0100
commit6abdcf82859e158713a3d5aa6b1012748ea5c2a0 (patch)
tree622b31927858c892ef03ea59bd41d93175c546fd
parentdcbab75db3ba5e812f119e08cda6a02c6b028a14 (diff)
downloadvim-git-6abdcf82859e158713a3d5aa6b1012748ea5c2a0.tar.gz
patch 8.2.2033: Vim9: :def without argument gives compilation errorv8.2.2033
Problem: Vim9: :def without argument gives compilation error. Solution: Add the DEF instruction. (closes #7344)
-rw-r--r--src/ex_docmd.c1
-rw-r--r--src/proto/userfunc.pro1
-rw-r--r--src/testdir/test_vim9_disassemble.vim23
-rw-r--r--src/testdir/test_vim9_func.vim27
-rw-r--r--src/userfunc.c2
-rw-r--r--src/version.c2
-rw-r--r--src/vim9.h1
-rw-r--r--src/vim9compile.c56
-rw-r--r--src/vim9execute.c23
9 files changed, 127 insertions, 9 deletions
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 2c35c8ef2..44e113d53 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -274,7 +274,6 @@ static void ex_tag_cmd(exarg_T *eap, char_u *name);
# define ex_continue ex_ni
# define ex_debug ex_ni
# define ex_debuggreedy ex_ni
-# define ex_def ex_ni
# define ex_defcompile ex_ni
# define ex_delfunction ex_ni
# define ex_disassemble ex_ni
diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro
index 7ee36dbc1..0029dab0d 100644
--- a/src/proto/userfunc.pro
+++ b/src/proto/userfunc.pro
@@ -33,6 +33,7 @@ int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typva
char_u *printable_func_name(ufunc_T *fp);
char_u *trans_function_name(char_u **pp, int *is_global, int skip, int flags, funcdict_T *fdp, partial_T **partial);
char_u *untrans_function_name(char_u *name);
+void list_functions(regmatch_T *regmatch);
ufunc_T *define_function(exarg_T *eap, char_u *name_arg);
void ex_function(exarg_T *eap);
void ex_defcompile(exarg_T *eap);
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
index 06fb77b0b..12a3c8269 100644
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -905,6 +905,29 @@ def Test_nested_func()
instr)
enddef
+def NestedDefList()
+ def
+ def Info
+ def /Info
+ def /Info/
+enddef
+
+def Test_nested_def_list()
+ var instr = execute('disassemble NestedDefList')
+ assert_match('NestedDefList\_s*' ..
+ 'def\_s*' ..
+ '\d DEF \_s*' ..
+ 'def Info\_s*' ..
+ '\d DEF Info\_s*' ..
+ 'def /Info\_s*' ..
+ '\d DEF /Info\_s*' ..
+ 'def /Info/\_s*' ..
+ '\d DEF /Info/\_s*' ..
+ '\d PUSHNR 0\_s*' ..
+ '\d RETURN',
+ instr)
+enddef
+
def AndOr(arg: any): string
if arg == 1 && arg != 2 || arg == 4
return 'yes'
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index dd2f576dd..80d564e3e 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -288,6 +288,33 @@ def Test_nested_global_function()
CheckScriptFailure(lines, "E1073:")
enddef
+def DefListAll()
+ def
+enddef
+
+def DefListOne()
+ def DefListOne
+enddef
+
+def DefListMatches()
+ def /DefList
+enddef
+
+def Test_nested_def_list()
+ var funcs = split(execute('call DefListAll()'), "\n")
+ assert_true(len(funcs) > 10)
+ assert_true(funcs->index('def DefListAll()') >= 0)
+
+ funcs = split(execute('call DefListOne()'), "\n")
+ assert_equal([' def DefListOne()', '1 def DefListOne', ' enddef'], funcs)
+
+ funcs = split(execute('call DefListMatches()'), "\n")
+ assert_true(len(funcs) >= 3)
+ assert_true(funcs->index('def DefListAll()') >= 0)
+ assert_true(funcs->index('def DefListOne()') >= 0)
+ assert_true(funcs->index('def DefListMatches()') >= 0)
+enddef
+
def Test_global_local_function()
var lines =<< trim END
vim9script
diff --git a/src/userfunc.c b/src/userfunc.c
index 7a306b1b7..70bbf33e1 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -2748,7 +2748,7 @@ untrans_function_name(char_u *name)
* List functions. When "regmatch" is NULL all of then.
* Otherwise functions matching "regmatch".
*/
- static void
+ void
list_functions(regmatch_T *regmatch)
{
int changed = func_hashtab.ht_changed;
diff --git a/src/version.c b/src/version.c
index 97c1e11ce..380710166 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2033,
+/**/
2032,
/**/
2031,
diff --git a/src/vim9.h b/src/vim9.h
index 60699f994..9685b9d57 100644
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -82,6 +82,7 @@ typedef enum {
ISN_RETURN, // return, result is on top of stack
ISN_FUNCREF, // push a function ref to dfunc isn_arg.funcref
ISN_NEWFUNC, // create a global function from a lambda function
+ ISN_DEF, // list functions
// expression operations
ISN_JUMP, // jump if condition is matched isn_arg.jump
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 7102d488f..b870023ea 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1433,6 +1433,26 @@ generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name)
}
/*
+ * Generate an ISN_DEF instruction: list functions
+ */
+ static int
+generate_DEF(cctx_T *cctx, char_u *name, size_t len)
+{
+ isn_T *isn;
+
+ RETURN_OK_IF_SKIP(cctx);
+ if ((isn = generate_instr(cctx, ISN_DEF)) == NULL)
+ return FAIL;
+ if (len > 0)
+ {
+ isn->isn_arg.string = vim_strnsave(name, len);
+ if (isn->isn_arg.string == NULL)
+ return FAIL;
+ }
+ return OK;
+}
+
+/*
* Generate an ISN_JUMP instruction.
*/
static int
@@ -4801,6 +4821,27 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
return NULL;
}
+ if (*name_start == '/')
+ {
+ name_end = skip_regexp(name_start + 1, '/', TRUE);
+ if (*name_end == '/')
+ ++name_end;
+ eap->nextcmd = check_nextcmd(name_end);
+ }
+ if (name_end == name_start || *skipwhite(name_end) != '(')
+ {
+ if (!ends_excmd2(name_start, name_end))
+ {
+ semsg(_(e_invalid_command_str), eap->cmd);
+ return NULL;
+ }
+
+ // "def" or "def Name": list functions
+ if (generate_DEF(cctx, name_start, name_end - name_start) == FAIL)
+ return NULL;
+ return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
+ }
+
// Only g:Func() can use a namespace.
if (name_start[1] == ':' && !is_global)
{
@@ -7736,22 +7777,23 @@ delete_instr(isn_T *isn)
{
switch (isn->isn_type)
{
+ case ISN_DEF:
case ISN_EXEC:
+ case ISN_LOADB:
case ISN_LOADENV:
case ISN_LOADG:
- case ISN_LOADB:
- case ISN_LOADW:
- case ISN_LOADT:
case ISN_LOADOPT:
- case ISN_STRINGMEMBER:
+ case ISN_LOADT:
+ case ISN_LOADW:
case ISN_PUSHEXC:
+ case ISN_PUSHFUNC:
case ISN_PUSHS:
+ case ISN_STOREB:
case ISN_STOREENV:
case ISN_STOREG:
- case ISN_STOREB:
- case ISN_STOREW:
case ISN_STORET:
- case ISN_PUSHFUNC:
+ case ISN_STOREW:
+ case ISN_STRINGMEMBER:
vim_free(isn->isn_arg.string);
break;
diff --git a/src/vim9execute.c b/src/vim9execute.c
index f15424907..8b614bfdc 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1970,6 +1970,20 @@ call_def_function(
}
break;
+ // List functions
+ case ISN_DEF:
+ if (iptr->isn_arg.string == NULL)
+ list_functions(NULL);
+ else
+ {
+ exarg_T ea;
+
+ CLEAR_FIELD(ea);
+ ea.cmd = ea.arg = iptr->isn_arg.string;
+ define_function(&ea, NULL);
+ }
+ break;
+
// jump if a condition is met
case ISN_JUMP:
{
@@ -3371,6 +3385,15 @@ ex_disassemble(exarg_T *eap)
}
break;
+ case ISN_DEF:
+ {
+ char_u *name = iptr->isn_arg.string;
+
+ smsg("%4d DEF %s", current,
+ name == NULL ? (char_u *)"" : name);
+ }
+ break;
+
case ISN_JUMP:
{
char *when = "?";