Patch 8.2.4053

7 views
Skip to first unread message

Bram Moolenaar

unread,
Jan 10, 2022, 1:09:00 PM1/10/22
to vim...@googlegroups.com

Patch 8.2.4053
Problem: Vim9: autoload mechanism doesn't fully work yet.
Solution: Define functions and variables with their autoload name, add the
prefix when calling a function, find the variable in the table of
script variables.
Files: src/structs.h, src/scriptfile.c, src/proto/scriptfile.pro,
src/vim9script.c, src/proto/vim9script.pro, src/userfunc.c,
src/evalvars.c, src/testdir/test_vim9_script.vim


*** ../vim-8.2.4052/src/structs.h 2022-01-09 21:32:57.709739119 +0000
--- src/structs.h 2022-01-10 17:31:10.464636150 +0000
***************
*** 1864,1870 ****
int sn_state; // SN_STATE_ values
char_u *sn_save_cpo; // 'cpo' value when :vim9script found
char sn_is_vimrc; // .vimrc file, do not restore 'cpo'
! char sn_is_autoload; // "vim9script autoload"

# ifdef FEAT_PROFILE
int sn_prof_on; // TRUE when script is/was profiled
--- 1864,1872 ----
int sn_state; // SN_STATE_ values
char_u *sn_save_cpo; // 'cpo' value when :vim9script found
char sn_is_vimrc; // .vimrc file, do not restore 'cpo'
!
! // for "vim9script autoload" this is "dir#scriptname#"
! char_u *sn_autoload_prefix;

# ifdef FEAT_PROFILE
int sn_prof_on; // TRUE when script is/was profiled
*** ../vim-8.2.4052/src/scriptfile.c 2022-01-10 11:26:27.913657607 +0000
--- src/scriptfile.c 2022-01-10 15:47:47.934211210 +0000
***************
*** 1711,1716 ****
--- 1711,1717 ----
# ifdef FEAT_PROFILE
ga_clear(&si->sn_prl_ga);
# endif
+ vim_free(si->sn_autoload_prefix);
vim_free(si);
}
ga_clear(&script_items);
***************
*** 2142,2147 ****
--- 2143,2183 ----
}

/*
+ * For an autoload script "autoload/dir/script.vim" return the prefix
+ * "dir#script#" in allocated memory.
+ * Returns NULL if anything is wrong.
+ */
+ char_u *
+ get_autoload_prefix(scriptitem_T *si)
+ {
+ char_u *p = script_name_after_autoload(si);
+ char_u *prefix;
+
+ if (p == NULL)
+ return NULL;
+ prefix = vim_strsave(p);
+ if (prefix == NULL)
+ return NULL;
+
+ // replace all '/' with '#' and locate ".vim" at the end
+ for (p = prefix; *p != NUL; p += mb_ptr2len(p))
+ {
+ if (vim_ispathsep(*p))
+ *p = '#';
+ else if (STRCMP(p, ".vim") == 0)
+ {
+ p[0] = '#';
+ p[1] = NUL;
+ return prefix;
+ }
+ }
+
+ // did not find ".vim" at the end
+ vim_free(prefix);
+ return NULL;
+ }
+
+ /*
* If in a Vim9 autoload script return "name" with the autoload prefix for the
* script. If successful "name" is freed, the returned name is allocated.
* Otherwise it returns "name" unmodified.
***************
*** 2153,2189 ****
{
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);

! if (si->sn_is_autoload)
{
! char_u *p = script_name_after_autoload(si);

! if (p != NULL)
{
! char_u *tail = vim_strsave(p);

! if (tail != NULL)
! {
! for (p = tail; *p != NUL; p += mb_ptr2len(p))
! {
! if (vim_ispathsep(*p))
! *p = '#';
! else if (STRCMP(p, ".vim"))
! {
! size_t len = (p - tail) + STRLEN(name) + 2;
! char_u *res = alloc(len);
!
! if (res == NULL)
! break;
! *p = NUL;
! vim_snprintf((char *)res, len, "%s#%s", tail, name);
! vim_free(name);
! vim_free(tail);
! return res;
! }
! }
! }
! // did not find ".vim" at the end
! vim_free(tail);
}
}
}
--- 2189,2216 ----
{
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);

! if (si->sn_autoload_prefix != NULL)
{
! char_u *basename = name;
! size_t len;
! char_u *res;

! if (*name == K_SPECIAL)
{
! char_u *p = vim_strchr(name, '_');

! // skip over "<SNR>99_"
! if (p != NULL)
! basename = p + 1;
! }
!
! len = STRLEN(si->sn_autoload_prefix) + STRLEN(basename) + 2;
! res = alloc(len);
! if (res != NULL)
! {
! vim_snprintf((char *)res, len, "%s%s",
! si->sn_autoload_prefix, basename);
! return res;
}
}
}
*** ../vim-8.2.4052/src/proto/scriptfile.pro 2022-01-09 21:32:57.709739119 +0000
--- src/proto/scriptfile.pro 2022-01-10 15:34:51.665158700 +0000
***************
*** 38,43 ****
--- 38,44 ----
void do_finish(exarg_T *eap, int reanimate);
int source_finished(char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie);
char_u *script_name_after_autoload(scriptitem_T *si);
+ char_u *get_autoload_prefix(scriptitem_T *si);
char_u *may_prefix_autoload(char_u *name);
char_u *autoload_name(char_u *name);
int script_autoload(char_u *name, int reload);
*** ../vim-8.2.4052/src/vim9script.c 2022-01-09 21:32:57.709739119 +0000
--- src/vim9script.c 2022-01-10 17:29:34.380663156 +0000
***************
*** 132,138 ****
}
si->sn_state = SN_STATE_HAD_COMMAND;

! si->sn_is_autoload = found_autoload;

current_sctx.sc_version = SCRIPT_VERSION_VIM9;
si->sn_version = SCRIPT_VERSION_VIM9;
--- 132,139 ----
}
si->sn_state = SN_STATE_HAD_COMMAND;

! // Store the prefix with the script. It isused to find exported functions.
! si->sn_autoload_prefix = get_autoload_prefix(si);

current_sctx.sc_version = SCRIPT_VERSION_VIM9;
si->sn_version = SCRIPT_VERSION_VIM9;
***************
*** 663,684 ****
}
else
{
char_u buffer[200];
char_u *funcname;

! // it could be a user function.
! if (STRLEN(name) < sizeof(buffer) - 15)
funcname = buffer;
else
{
! funcname = alloc(STRLEN(name) + 15);
if (funcname == NULL)
return -1;
}
! funcname[0] = K_SPECIAL;
! funcname[1] = KS_EXTRA;
! funcname[2] = (int)KE_SNR;
! sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
*ufunc = find_func(funcname, FALSE, NULL);
if (funcname != buffer)
vim_free(funcname);
--- 664,700 ----
}
else
{
+ size_t len = STRLEN(name);
char_u buffer[200];
char_u *funcname;

! // It could be a user function. Normally this is stored as
! // "<SNR>99_name". For an autoload script a function is stored with
! // the autoload prefix: "dir#script#name".
! if (script->sn_autoload_prefix != NULL)
! len += STRLEN(script->sn_autoload_prefix) + 2;
! else
! len += 15;
!
! if (len < sizeof(buffer))
funcname = buffer;
else
{
! funcname = alloc(len);
if (funcname == NULL)
return -1;
}
! if (script->sn_autoload_prefix != NULL)
! {
! sprintf((char *)funcname, "%s%s", script->sn_autoload_prefix, name);
! }
! else
! {
! funcname[0] = K_SPECIAL;
! funcname[1] = KS_EXTRA;
! funcname[2] = (int)KE_SNR;
! sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
! }
*ufunc = find_func(funcname, FALSE, NULL);
if (funcname != buffer)
vim_free(funcname);
***************
*** 782,787 ****
--- 798,804 ----
update_vim9_script_var(
int create,
dictitem_T *di,
+ char_u *name,
int flags,
typval_T *tv,
type_T **type,
***************
*** 801,807 ****
if (ga_grow(&si->sn_var_vals, 1) == FAIL)
return;

! hi = hash_find(&si->sn_all_vars.dv_hashtab, di->di_key);
if (!HASHITEM_EMPTY(hi))
{
// Variable with this name exists, either in this block or in
--- 818,824 ----
if (ga_grow(&si->sn_var_vals, 1) == FAIL)
return;

! hi = hash_find(&si->sn_all_vars.dv_hashtab, name);
if (!HASHITEM_EMPTY(hi))
{
// Variable with this name exists, either in this block or in
***************
*** 833,839 ****
// svar_T and create a new sallvar_T.
sv = ((svar_T *)si->sn_var_vals.ga_data) + si->sn_var_vals.ga_len;
newsav = (sallvar_T *)alloc_clear(
! sizeof(sallvar_T) + STRLEN(di->di_key));
if (newsav == NULL)
return;

--- 850,856 ----
// svar_T and create a new sallvar_T.
sv = ((svar_T *)si->sn_var_vals.ga_data) + si->sn_var_vals.ga_len;
newsav = (sallvar_T *)alloc_clear(
! sizeof(sallvar_T) + STRLEN(name));
if (newsav == NULL)
return;

***************
*** 843,849 ****
sv->sv_export = is_export;
newsav->sav_var_vals_idx = si->sn_var_vals.ga_len;
++si->sn_var_vals.ga_len;
! STRCPY(&newsav->sav_key, di->di_key);
sv->sv_name = newsav->sav_key;
newsav->sav_di = di;
newsav->sav_block_id = si->sn_current_block_id;
--- 860,866 ----
sv->sv_export = is_export;
newsav->sav_var_vals_idx = si->sn_var_vals.ga_len;
++si->sn_var_vals.ga_len;
! STRCPY(&newsav->sav_key, name);
sv->sv_name = newsav->sav_key;
newsav->sav_di = di;
newsav->sav_block_id = si->sn_current_block_id;
*** ../vim-8.2.4052/src/proto/vim9script.pro 2022-01-06 21:10:24.465027868 +0000
--- src/proto/vim9script.pro 2022-01-10 17:30:49.312643816 +0000
***************
*** 13,19 ****
void ex_import(exarg_T *eap);
int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx, int verbose);
char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg);
! void update_vim9_script_var(int create, dictitem_T *di, int flags, typval_T *tv, type_T **type, int do_member);
void hide_script_var(scriptitem_T *si, int idx, int func_defined);
svar_T *find_typval_in_script(typval_T *dest, scid_T sid);
int check_script_var_type(svar_T *sv, typval_T *value, char_u *name, where_T where);
--- 13,19 ----
void ex_import(exarg_T *eap);
int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx, int verbose);
char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg);
! void update_vim9_script_var(int create, dictitem_T *di, char_u *name, int flags, typval_T *tv, type_T **type, int do_member);
void hide_script_var(scriptitem_T *si, int idx, int func_defined);
svar_T *find_typval_in_script(typval_T *dest, scid_T sid);
int check_script_var_type(svar_T *sv, typval_T *value, char_u *name, where_T where);
*** ../vim-8.2.4052/src/userfunc.c 2022-01-09 21:32:57.709739119 +0000
--- src/userfunc.c 2022-01-10 15:09:29.206253888 +0000
***************
*** 4080,4087 ****
eap->skip = TRUE;
}

! // if (is_export)
! // name = may_prefix_autoload(name);
}

// An error in a function call during evaluation of an expression in magic
--- 4080,4090 ----
eap->skip = TRUE;
}

! // For "export def FuncName()" in an autoload script the function name
! // is stored with the legacy autoload name "dir#script#FuncName" so
! // that it can also be found in legacy script.
! if (is_export)
! name = may_prefix_autoload(name);
}

// An error in a function call during evaluation of an expression in magic
*** ../vim-8.2.4052/src/evalvars.c 2022-01-09 21:32:57.713739111 +0000
--- src/evalvars.c 2022-01-10 17:35:06.940495934 +0000
***************
*** 3339,3348 ****
--- 3339,3350 ----
dictitem_T *di;
typval_T *dest_tv = NULL;
char_u *varname;
+ char_u *name_tofree = NULL;
hashtab_T *ht = NULL;
int is_script_local;
int vim9script = in_vim9script();
int var_in_vim9script;
+ int var_in_autoload = FALSE;
int flags = flags_arg;
int free_tv_arg = !copy; // free tv_arg if not used

***************
*** 3353,3365 ****
varname = name;
}
else
! ht = find_var_ht(name, &varname);
if (ht == NULL || *varname == NUL)
{
semsg(_(e_illegal_variable_name_str), name);
goto failed;
}
! is_script_local = ht == get_script_local_ht() || sid != 0;

if (vim9script
&& !is_script_local
--- 3355,3388 ----
varname = name;
}
else
! {
! if (in_vim9script() && SCRIPT_ID_VALID(current_sctx.sc_sid)
! && SCRIPT_ITEM(current_sctx.sc_sid)->sn_autoload_prefix != NULL
! && is_export)
! {
! scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
! size_t len = STRLEN(name) + STRLEN(si->sn_autoload_prefix) + 1;
!
! // In a vim9 autoload script an exported variable is put in the
! // global namespace with the autoload prefix.
! var_in_autoload = TRUE;
! varname = alloc(len);
! if (varname == NULL)
! goto failed;
! name_tofree = varname;
! vim_snprintf((char *)varname, len, "%s%s",
! si->sn_autoload_prefix, name);
! ht = &globvarht;
! }
! else
! ht = find_var_ht(name, &varname);
! }
if (ht == NULL || *varname == NUL)
{
semsg(_(e_illegal_variable_name_str), name);
goto failed;
}
! is_script_local = ht == get_script_local_ht() || sid != 0 || var_in_autoload;

if (vim9script
&& !is_script_local
***************
*** 3470,3478 ****

// A Vim9 script-local variable is also present in sn_all_vars
// and sn_var_vals. It may set "type" from "tv".
! if (var_in_vim9script)
! update_vim9_script_var(FALSE, di, flags, tv, &type,
! (flags & ASSIGN_NO_MEMBER_TYPE) == 0);
}

// existing variable, need to clear the value
--- 3493,3502 ----

// A Vim9 script-local variable is also present in sn_all_vars
// and sn_var_vals. It may set "type" from "tv".
! if (var_in_vim9script || var_in_autoload)
! update_vim9_script_var(FALSE, di,
! var_in_autoload ? name : di->di_key, flags,
! tv, &type, (flags & ASSIGN_NO_MEMBER_TYPE) == 0);
}

// existing variable, need to clear the value
***************
*** 3550,3559 ****
goto failed;
}

! // Make sure the variable name is valid. In Vim9 script an autoload
! // variable must be prefixed with "g:".
if (!valid_varname(varname, -1, !vim9script
! || STRNCMP(name, "g:", 2) == 0))
goto failed;

di = alloc(sizeof(dictitem_T) + STRLEN(varname));
--- 3574,3584 ----
goto failed;
}

! // Make sure the variable name is valid. In Vim9 script an
! // autoload variable must be prefixed with "g:" unless in an
! // autoload script.
if (!valid_varname(varname, -1, !vim9script
! || STRNCMP(name, "g:", 2) == 0 || var_in_autoload))
goto failed;

di = alloc(sizeof(dictitem_T) + STRLEN(varname));
***************
*** 3571,3579 ****

// A Vim9 script-local variable is also added to sn_all_vars and
// sn_var_vals. It may set "type" from "tv".
! if (var_in_vim9script)
! update_vim9_script_var(TRUE, di, flags, tv, &type,
! (flags & ASSIGN_NO_MEMBER_TYPE) == 0);
}

dest_tv = &di->di_tv;
--- 3596,3605 ----

// A Vim9 script-local variable is also added to sn_all_vars and
// sn_var_vals. It may set "type" from "tv".
! if (var_in_vim9script || var_in_autoload)
! update_vim9_script_var(TRUE, di,
! var_in_autoload ? name : di->di_key, flags,
! tv, &type, (flags & ASSIGN_NO_MEMBER_TYPE) == 0);
}

dest_tv = &di->di_tv;
***************
*** 3618,3623 ****
--- 3644,3650 ----
item_lock(dest_tv, DICT_MAXNEST, TRUE, TRUE);

failed:
+ vim_free(name_tofree);
if (free_tv_arg)
clear_tv(tv_arg);
}
*** ../vim-8.2.4052/src/testdir/test_vim9_script.vim 2022-01-09 21:32:57.713739111 +0000
--- src/testdir/test_vim9_script.vim 2022-01-10 17:53:36.878611178 +0000
***************
*** 3049,3054 ****
--- 3049,3062 ----
assert_false(exists('g:prefixed_loaded'))
assert_equal('test', prefixed.Gettest())
assert_equal('yes', g:prefixed_loaded)
+ assert_equal('name', prefixed.name)
+ END
+ CheckScriptSuccess(lines)
+
+ # can also get the items by autoload name
+ lines =<< trim END
+ call assert_equal('test', prefixed#Gettest())
+ call assert_equal('name', prefixed#name)
END
CheckScriptSuccess(lines)

*** ../vim-8.2.4052/src/version.c 2022-01-10 13:36:31.264892417 +0000
--- src/version.c 2022-01-10 15:49:28.510212127 +0000
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 4053,
/**/

--
MAN: Fetchez la vache!
GUARD: Quoi?
MAN: Fetchez la vache!
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

/// 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 ///
Reply all
Reply to author
Forward
0 new messages