summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/vim9.txt9
-rw-r--r--src/ex_cmds.h2
-rw-r--r--src/proto/userfunc.pro1
-rw-r--r--src/testdir/test_vim9_cmd.vim10
-rw-r--r--src/testdir/test_vim9_disassemble.vim3
-rw-r--r--src/userfunc.c119
-rw-r--r--src/version.c2
-rw-r--r--src/vim9execute.c44
8 files changed, 126 insertions, 64 deletions
diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt
index 5a0e5bf88..479edc57c 100644
--- a/runtime/doc/vim9.txt
+++ b/runtime/doc/vim9.txt
@@ -1210,7 +1210,14 @@ prefix if they do not exist at the time of compiling.
*:defc* *:defcompile*
:defc[ompile] Compile functions defined in the current script that
were not compiled yet.
- This will report errors found during the compilation.
+ This will report any errors found during compilation.
+
+:defc[ompile] {func}
+:defc[ompile] debug {func}
+:defc[ompile] profile {func}
+ Compile function {func}, if needed. Use "debug" and
+ "profile" to specify the compilation mode.
+ This will report any errors found during compilation.
*:disa* *:disassemble*
:disa[ssemble] {func} Show the instructions generated for {func}.
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index e4f9bb05d..b8cf41d44 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -465,7 +465,7 @@ EXCMD(CMD_def, "def", ex_function,
EX_EXTRA|EX_BANG|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
ADDR_NONE),
EXCMD(CMD_defcompile, "defcompile", ex_defcompile,
- EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_TRLBAR,
+ EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK|EX_TRLBAR|EX_EXTRA,
ADDR_NONE),
EXCMD(CMD_delcommand, "delcommand", ex_delcommand,
EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro
index 7bedac07b..537276013 100644
--- a/src/proto/userfunc.pro
+++ b/src/proto/userfunc.pro
@@ -45,6 +45,7 @@ char_u *save_function_name(char_u **name, int *is_global, int skip, int flags, f
void list_functions(regmatch_T *regmatch);
ufunc_T *define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free);
void ex_function(exarg_T *eap);
+ufunc_T *find_func_by_name(char_u *name, compiletype_T *compile_type);
void ex_defcompile(exarg_T *eap);
int eval_fname_script(char_u *p);
int translated_function_exists(char_u *name, int is_global);
diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim
index 77e1d8a06..7db8e50c8 100644
--- a/src/testdir/test_vim9_cmd.vim
+++ b/src/testdir/test_vim9_cmd.vim
@@ -83,6 +83,16 @@ def Test_vim9cmd()
v9.CheckScriptSuccess(lines)
enddef
+def Test_defcompile_fails()
+ assert_fails('defcompile NotExists', 'E1061:')
+ assert_fails('defcompile debug debug Test_defcompile_fails', 'E488:')
+ assert_fails('defcompile profile profile Test_defcompile_fails', 'E488:')
+enddef
+
+defcompile Test_defcompile_fails
+defcompile debug Test_defcompile_fails
+defcompile profile Test_defcompile_fails
+
def Test_cmdmod_execute()
# "legacy" applies not only to the "exe" argument but also to the commands
var lines =<< trim END
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
index c99c8b4fa..78604950b 100644
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -43,6 +43,9 @@ def Test_disassemble_load()
assert_fails('disass [', 'E475:')
assert_fails('disass 234', 'E129:')
assert_fails('disass <XX>foo', 'E129:')
+ assert_fails('disass Test_disassemble_load burp', 'E488:')
+ assert_fails('disass debug debug Test_disassemble_load', 'E488:')
+ assert_fails('disass profile profile Test_disassemble_load', 'E488:')
var res = execute('disass s:ScriptFuncLoad')
assert_match('<SNR>\d*_ScriptFuncLoad.*' ..
diff --git a/src/userfunc.c b/src/userfunc.c
index 42e285fca..6eabd8b77 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -4997,36 +4997,115 @@ ex_function(exarg_T *eap)
}
/*
+ * Find a function by name, including "<lambda>123".
+ * Check for "profile" and "debug" arguments and set"compile_type".
+ * Return NULL if not found.
+ */
+ ufunc_T *
+find_func_by_name(char_u *name, compiletype_T *compile_type)
+{
+ char_u *arg = name;
+ char_u *fname;
+ ufunc_T *ufunc;
+ int is_global = FALSE;
+
+ *compile_type = CT_NONE;
+ if (STRNCMP(arg, "profile", 7) == 0 && VIM_ISWHITE(arg[7]))
+ {
+ *compile_type = CT_PROFILE;
+ arg = skipwhite(arg + 7);
+ }
+ else if (STRNCMP(arg, "debug", 5) == 0 && VIM_ISWHITE(arg[5]))
+ {
+ *compile_type = CT_DEBUG;
+ arg = skipwhite(arg + 5);
+ }
+
+ if (STRNCMP(arg, "<lambda>", 8) == 0)
+ {
+ arg += 8;
+ (void)getdigits(&arg);
+ fname = vim_strnsave(name, arg - name);
+ }
+ else
+ fname = trans_function_name(&arg, &is_global, FALSE,
+ TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL, NULL);
+ if (fname == NULL)
+ {
+ semsg(_(e_invalid_argument_str), name);
+ return NULL;
+ }
+ if (!ends_excmd2(name, arg))
+ {
+ emsg(ex_errmsg(e_trailing_characters_str, arg));
+ return NULL;
+ }
+
+ ufunc = find_func(fname, is_global);
+ if (ufunc == NULL)
+ {
+ char_u *p = untrans_function_name(fname);
+
+ if (p != NULL)
+ // Try again without making it script-local.
+ ufunc = find_func(p, FALSE);
+ }
+ vim_free(fname);
+ if (ufunc == NULL)
+ semsg(_(e_cannot_find_function_str), name);
+ return ufunc;
+}
+
+/*
* :defcompile - compile all :def functions in the current script that need to
- * be compiled. Except dead functions. Doesn't do profiling.
+ * be compiled or the one specified by the argument.
+ * Skips dead functions. Doesn't do profiling.
*/
void
-ex_defcompile(exarg_T *eap UNUSED)
+ex_defcompile(exarg_T *eap)
{
- long todo = (long)func_hashtab.ht_used;
- int changed = func_hashtab.ht_changed;
- hashitem_T *hi;
ufunc_T *ufunc;
- for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
+ if (*eap->arg != NUL)
{
- if (!HASHITEM_EMPTY(hi))
+ compiletype_T compile_type;
+
+ ufunc = find_func_by_name(eap->arg, &compile_type);
+ if (ufunc != NULL)
{
- --todo;
- ufunc = HI2UF(hi);
- if (ufunc->uf_script_ctx.sc_sid == current_sctx.sc_sid
- && ufunc->uf_def_status == UF_TO_BE_COMPILED
- && (ufunc->uf_flags & FC_DEAD) == 0)
- {
- (void)compile_def_function(ufunc, FALSE, CT_NONE, NULL);
+ if (func_needs_compiling(ufunc, compile_type))
+ (void)compile_def_function(ufunc, FALSE, compile_type, NULL);
+ else
+ smsg(_("Function %s does not need compiling"), eap->arg);
+ }
+ }
+ else
+ {
+ long todo = (long)func_hashtab.ht_used;
+ int changed = func_hashtab.ht_changed;
+ hashitem_T *hi;
- if (func_hashtab.ht_changed != changed)
+ for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
+ {
+ if (!HASHITEM_EMPTY(hi))
+ {
+ --todo;
+ ufunc = HI2UF(hi);
+ if (ufunc->uf_script_ctx.sc_sid == current_sctx.sc_sid
+ && ufunc->uf_def_status == UF_TO_BE_COMPILED
+ && (ufunc->uf_flags & FC_DEAD) == 0)
{
- // a function has been added or removed, need to start over
- todo = (long)func_hashtab.ht_used;
- changed = func_hashtab.ht_changed;
- hi = func_hashtab.ht_array;
- --hi;
+ (void)compile_def_function(ufunc, FALSE, CT_NONE, NULL);
+
+ if (func_hashtab.ht_changed != changed)
+ {
+ // a function has been added or removed, need to start
+ // over
+ todo = (long)func_hashtab.ht_used;
+ changed = func_hashtab.ht_changed;
+ hi = func_hashtab.ht_array;
+ --hi;
+ }
}
}
}
diff --git a/src/version.c b/src/version.c
index ec25334d3..c6e6a391f 100644
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4989,
+/**/
4988,
/**/
4987,
diff --git a/src/vim9execute.c b/src/vim9execute.c
index a64ae5cbb..d89f44236 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -6277,55 +6277,15 @@ get_disassemble_argument(expand_T *xp, int idx)
ex_disassemble(exarg_T *eap)
{
char_u *arg = eap->arg;
- char_u *fname;
ufunc_T *ufunc;
dfunc_T *dfunc;
isn_T *instr;
int instr_count;
- int is_global = FALSE;
- compiletype_T compile_type = CT_NONE;
-
- if (STRNCMP(arg, "profile", 7) == 0 && VIM_ISWHITE(arg[7]))
- {
- compile_type = CT_PROFILE;
- arg = skipwhite(arg + 7);
- }
- else if (STRNCMP(arg, "debug", 5) == 0 && VIM_ISWHITE(arg[5]))
- {
- compile_type = CT_DEBUG;
- arg = skipwhite(arg + 5);
- }
-
- if (STRNCMP(arg, "<lambda>", 8) == 0)
- {
- arg += 8;
- (void)getdigits(&arg);
- fname = vim_strnsave(eap->arg, arg - eap->arg);
- }
- else
- fname = trans_function_name(&arg, &is_global, FALSE,
- TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD, NULL, NULL, NULL);
- if (fname == NULL)
- {
- semsg(_(e_invalid_argument_str), eap->arg);
- return;
- }
-
- ufunc = find_func(fname, is_global);
- if (ufunc == NULL)
- {
- char_u *p = untrans_function_name(fname);
+ compiletype_T compile_type;
- if (p != NULL)
- // Try again without making it script-local.
- ufunc = find_func(p, FALSE);
- }
- vim_free(fname);
+ ufunc = find_func_by_name(arg, &compile_type);
if (ufunc == NULL)
- {
- semsg(_(e_cannot_find_function_str), eap->arg);
return;
- }
if (func_needs_compiling(ufunc, compile_type)
&& compile_def_function(ufunc, FALSE, compile_type, NULL) == FAIL)
return;