diff options
-rw-r--r-- | runtime/doc/vim9.txt | 9 | ||||
-rw-r--r-- | src/ex_cmds.h | 2 | ||||
-rw-r--r-- | src/proto/userfunc.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_vim9_cmd.vim | 10 | ||||
-rw-r--r-- | src/testdir/test_vim9_disassemble.vim | 3 | ||||
-rw-r--r-- | src/userfunc.c | 119 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9execute.c | 44 |
8 files changed, 126 insertions, 64 deletions
diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index 5a0e5bf880..479edc57c5 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 e4f9bb05db..b8cf41d44c 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 7bedac07bf..537276013a 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 77e1d8a069..7db8e50c8e 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 c99c8b4fa4..78604950b9 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 42e285fca1..6eabd8b77f 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 ec25334d3f..c6e6a391f3 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 a64ae5cbbd..d89f442367 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; |