Patch 8.2.4989
Problem: Cannot specify a function name for :defcompile.
Solution: Implement a function name argument for :defcompile.
Files: runtime/doc/vim9.txt, src/userfunc.c, src/proto/
userfunc.pro,
src/vim9execute.c, src/ex_cmds.h, src/testdir/test_vim9_cmd.vim,
src/testdir/test_vim9_disassemble.vim
*** ../vim-8.2.4988/runtime/doc/vim9.txt 2022-04-14 12:58:19.604895030 +0100
--- runtime/doc/vim9.txt 2022-05-21 15:19:15.069829376 +0100
***************
*** 1167,1177 ****
*:defc* *:defcompile*
:defc[ompile] Compile functions defined in the current script that
were not compiled yet.
! This will report errors found during the compilation.
*:disa* *:disassemble*
:disa[ssemble] {func} Show the instructions generated for {func}.
! This is for debugging and testing.
Note that for command line completion of {func} you
can prepend "s:" to find script-local functions.
--- 1210,1227 ----
*:defc* *:defcompile*
:defc[ompile] Compile functions defined in the current script that
were not compiled yet.
! 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}.
! This is for debugging and testing. *E1061*
Note that for command line completion of {func} you
can prepend "s:" to find script-local functions.
*** ../vim-8.2.4988/src/userfunc.c 2022-05-13 13:50:32.815012765 +0100
--- src/userfunc.c 2022-05-21 15:07:41.701381219 +0100
***************
*** 4997,5032 ****
}
/*
* :defcompile - compile all :def functions in the current script that need to
! * be compiled. Except dead functions. Doesn't do profiling.
*/
void
! ex_defcompile(exarg_T *eap UNUSED)
{
- 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 (!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)
! {
! (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;
}
}
}
--- 4997,5111 ----
}
/*
+ * 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 or the one specified by the argument.
! * Skips dead functions. Doesn't do profiling.
*/
void
! ex_defcompile(exarg_T *eap)
{
ufunc_T *ufunc;
! if (*eap->arg != NUL)
{
! compiletype_T compile_type;
!
! ufunc = find_func_by_name(eap->arg, &compile_type);
! if (ufunc != 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;
! 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)
{
! (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;
! }
}
}
}
*** ../vim-8.2.4988/src/proto/
userfunc.pro 2022-03-31 20:02:52.422045605 +0100
--- src/proto/
userfunc.pro 2022-05-21 14:25:55.757001488 +0100
***************
*** 45,50 ****
--- 45,51 ----
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);
*** ../vim-8.2.4988/src/vim9execute.c 2022-05-18 11:00:44.295519512 +0100
--- src/vim9execute.c 2022-05-21 14:24:16.605069858 +0100
***************
*** 6277,6331 ****
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);
!
! 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), eap->arg);
return;
- }
if (func_needs_compiling(ufunc, compile_type)
&& compile_def_function(ufunc, FALSE, compile_type, NULL) == FAIL)
return;
--- 6277,6291 ----
ex_disassemble(exarg_T *eap)
{
char_u *arg = eap->arg;
ufunc_T *ufunc;
dfunc_T *dfunc;
isn_T *instr;
int instr_count;
! compiletype_T compile_type;
! ufunc = find_func_by_name(arg, &compile_type);
if (ufunc == NULL)
return;
if (func_needs_compiling(ufunc, compile_type)
&& compile_def_function(ufunc, FALSE, compile_type, NULL) == FAIL)
return;
*** ../vim-8.2.4988/src/ex_cmds.h 2022-03-24 11:22:07.215294108 +0000
--- src/ex_cmds.h 2022-05-21 15:13:35.921471148 +0100
***************
*** 465,471 ****
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,
ADDR_NONE),
EXCMD(CMD_delcommand, "delcommand", ex_delcommand,
EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
--- 465,471 ----
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_EXTRA,
ADDR_NONE),
EXCMD(CMD_delcommand, "delcommand", ex_delcommand,
EX_NEEDARG|EX_WORD1|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
*** ../vim-8.2.4988/src/testdir/test_vim9_cmd.vim 2022-05-17 12:45:11.789423526 +0100
--- src/testdir/test_vim9_cmd.vim 2022-05-21 15:15:44.369638126 +0100
***************
*** 83,88 ****
--- 83,98 ----
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
*** ../vim-8.2.4988/src/testdir/test_vim9_disassemble.vim 2022-05-17 16:12:35.712086412 +0100
--- src/testdir/test_vim9_disassemble.vim 2022-05-21 15:09:29.405340070 +0100
***************
*** 43,48 ****
--- 43,51 ----
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.*' ..
*** ../vim-8.2.4988/src/version.c 2022-05-21 11:20:38.102070988 +0100
--- src/version.c 2022-05-21 14:20:10.761214621 +0100
***************
*** 748,749 ****
--- 748,751 ----
{ /* Add new patch number below this line */
+ /**/
+ 4989,
/**/
--
hundred-and-one symptoms of being an internet addict:
243. You unsuccessfully try to download a pizza from
www.dominos.com.
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///