To: vim_dev@googlegroups.com Subject: Patch 8.2.2225 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2225 Problem: Vim9: error when using :import in legacy script twice. Solution: Make it possible to redefine an import when reloading. Files: src/vim9script.c, src/proto/vim9script.pro, src/structs.h, src/evalvars.c, src/vim9compile.c, src/testdir/test_vim9_script.vim *** ../vim-8.2.2224/src/vim9script.c 2020-12-26 20:09:11.286465244 +0100 --- src/vim9script.c 2020-12-27 13:05:28.213923518 +0100 *************** *** 174,179 **** --- 174,197 ---- } /* + * Mark all imports as possible to redefine. Used when a script is loaded + * again but not cleared. + */ + void + mark_imports_for_reload(int sid) + { + scriptitem_T *si = SCRIPT_ITEM(sid); + int idx; + + for (idx = 0; idx < si->sn_imports.ga_len; ++idx) + { + imported_T *imp = ((imported_T *)si->sn_imports.ga_data) + idx; + + imp->imp_flags |= IMP_FLAGS_RELOAD; + } + } + + /* * ":import Item from 'filename'" * ":import Item as Alias from 'filename'" * ":import {Item} from 'filename'". *************** *** 459,473 **** if (*arg_start == '*') { ! imported_T *imported = new_imported(gap != NULL ? gap ! : &SCRIPT_ITEM(import_sid)->sn_imports); if (imported == NULL) goto erret; imported->imp_name = as_name; as_name = NULL; imported->imp_sid = sid; ! imported->imp_all = TRUE; } else { --- 477,505 ---- if (*arg_start == '*') { ! imported_T *imported; + imported = find_imported(as_name, STRLEN(as_name), cctx); + if (imported != NULL && imported->imp_sid == sid) + { + if (imported->imp_flags & IMP_FLAGS_RELOAD) + // import already defined on a previous script load + imported->imp_flags &= ~IMP_FLAGS_RELOAD; + else + { + semsg(_(e_name_already_defined_str), as_name); + goto erret; + } + } + + imported = new_imported(gap != NULL ? gap + : &SCRIPT_ITEM(import_sid)->sn_imports); if (imported == NULL) goto erret; imported->imp_name = as_name; as_name = NULL; imported->imp_sid = sid; ! imported->imp_flags = IMP_FLAGS_STAR; } else { *************** *** 479,484 **** --- 511,517 ---- for (i = 0; i < names.ga_len; ++i) { char_u *name = ((char_u **)names.ga_data)[i]; + size_t len = STRLEN(name); int idx; imported_T *imported; ufunc_T *ufunc = NULL; *************** *** 489,516 **** if (idx < 0 && ufunc == NULL) goto erret; ! if (check_defined(name, STRLEN(name), cctx) == FAIL) ! goto erret; ! ! imported = new_imported(gap != NULL ? gap ! : &SCRIPT_ITEM(import_sid)->sn_imports); ! if (imported == NULL) ! goto erret; ! ! // TODO: check for "as" following ! // imported->imp_name = vim_strsave(as_name); ! imported->imp_name = name; ! ((char_u **)names.ga_data)[i] = NULL; ! imported->imp_sid = sid; ! if (idx >= 0) { ! imported->imp_type = type; ! imported->imp_var_vals_idx = idx; } else { ! imported->imp_type = ufunc->uf_func_type; ! imported->imp_funcname = ufunc->uf_name; } } } --- 522,568 ---- if (idx < 0 && ufunc == NULL) goto erret; ! // If already imported with the same propertis and the ! // IMP_FLAGS_RELOAD set then we keep that entry. Otherwise create ! // a new one (and give an error for an existing import). ! imported = find_imported(name, len, cctx); ! if (imported != NULL ! && (imported->imp_flags & IMP_FLAGS_RELOAD) ! && imported->imp_sid == sid ! && (idx >= 0 ! ? (equal_type(imported->imp_type, type) ! && imported->imp_var_vals_idx == idx) ! : (equal_type(imported->imp_type, ufunc->uf_func_type) ! && STRCMP(imported->imp_funcname, ! ufunc->uf_name) == 0))) { ! imported->imp_flags &= ~IMP_FLAGS_RELOAD; } else { ! if (check_defined(name, len, cctx) == FAIL) ! goto erret; ! ! imported = new_imported(gap != NULL ? gap ! : &SCRIPT_ITEM(import_sid)->sn_imports); ! if (imported == NULL) ! goto erret; ! ! // TODO: check for "as" following ! // imported->imp_name = vim_strsave(as_name); ! imported->imp_name = name; ! ((char_u **)names.ga_data)[i] = NULL; ! imported->imp_sid = sid; ! if (idx >= 0) ! { ! imported->imp_type = type; ! imported->imp_var_vals_idx = idx; ! } ! else ! { ! imported->imp_type = ufunc->uf_func_type; ! imported->imp_funcname = ufunc->uf_name; ! } } } } *** ../vim-8.2.2224/src/proto/vim9script.pro 2020-12-26 20:09:11.286465244 +0100 --- src/proto/vim9script.pro 2020-12-27 12:46:36.053572738 +0100 *************** *** 4,9 **** --- 4,10 ---- int not_in_vim9(exarg_T *eap); void ex_export(exarg_T *eap); void free_imports_and_script_vars(int sid); + void mark_imports_for_reload(int sid); void ex_import(exarg_T *eap); int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type, cctx_T *cctx); char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid, evalarg_T *evalarg, void *cctx); *** ../vim-8.2.2224/src/structs.h 2020-12-26 15:39:24.615550807 +0100 --- src/structs.h 2020-12-27 12:41:44.154834241 +0100 *************** *** 1778,1794 **** char_u *imp_name; // name imported as (allocated) int imp_sid; // script ID of "from" ! // for "import * as Name", "imp_name" is "Name" ! int imp_all; ! // for variable type_T *imp_type; int imp_var_vals_idx; // index in sn_var_vals of "from" ! // for function char_u *imp_funcname; // user func name (NOT allocated) } imported_T; /* * Info about an already sourced scripts. */ --- 1778,1796 ---- char_u *imp_name; // name imported as (allocated) int imp_sid; // script ID of "from" ! int imp_flags; // IMP_FLAGS_ values ! // for a variable type_T *imp_type; int imp_var_vals_idx; // index in sn_var_vals of "from" ! // for a function char_u *imp_funcname; // user func name (NOT allocated) } imported_T; + #define IMP_FLAGS_STAR 1 // using "import * as Name" + #define IMP_FLAGS_RELOAD 2 // script reloaded, OK to redefine + /* * Info about an already sourced scripts. */ *** ../vim-8.2.2224/src/evalvars.c 2020-12-26 20:09:11.286465244 +0100 --- src/evalvars.c 2020-12-26 21:48:11.792575642 +0100 *************** *** 2531,2537 **** rettv->vval.v_string = vim_strsave(import->imp_funcname); } } ! else if (import->imp_all) { emsg("Sorry, 'import * as X' not implemented yet"); ret = FAIL; --- 2531,2537 ---- rettv->vval.v_string = vim_strsave(import->imp_funcname); } } ! else if (import->imp_flags & IMP_FLAGS_STAR) { emsg("Sorry, 'import * as X' not implemented yet"); ret = FAIL; *** ../vim-8.2.2224/src/vim9compile.c 2020-12-26 20:09:11.282465257 +0100 --- src/vim9compile.c 2020-12-26 21:48:59.876426066 +0100 *************** *** 2416,2422 **** import = find_imported(name, 0, cctx); if (import != NULL) { ! if (import->imp_all) { char_u *p = skipwhite(*end); char_u *exp_name; --- 2416,2422 ---- import = find_imported(name, 0, cctx); if (import != NULL) { ! if (import->imp_flags & IMP_FLAGS_STAR) { char_u *p = skipwhite(*end); char_u *exp_name; *** ../vim-8.2.2224/src/testdir/test_vim9_script.vim 2020-12-26 20:09:11.286465244 +0100 --- src/testdir/test_vim9_script.vim 2020-12-27 13:38:08.523351440 +0100 *************** *** 899,904 **** --- 899,914 ---- writefile(import_star_as_lines_dot_space, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1074:', '', 1, 'Func') + var import_star_as_duplicated =<< trim END + vim9script + import * as Export from './Xexport.vim' + var some = 'other' + import * as Export from './Xexport.vim' + defcompile + END + writefile(import_star_as_duplicated, 'Ximport.vim') + assert_fails('source Ximport.vim', 'E1073:', '', 4, 'Ximport.vim') + var import_star_as_lines_missing_name =<< trim END vim9script import * as Export from './Xexport.vim' *************** *** 1160,1168 **** --- 1170,1184 ---- def Test_vim9script_reload_noclear() var lines =<< trim END + vim9script + export var exported = 'thexport' + END + writefile(lines, 'XExportReload') + lines =<< trim END vim9script noclear g:loadCount += 1 var s:reloaded = 'init' + import exported from './XExportReload' def Again(): string return 'again' *************** *** 1174,1180 **** var s:notReloaded = 'yes' s:reloaded = 'first' def g:Values(): list ! return [s:reloaded, s:notReloaded, Again(), Once()] enddef def Once(): string --- 1190,1196 ---- var s:notReloaded = 'yes' s:reloaded = 'first' def g:Values(): list ! return [s:reloaded, s:notReloaded, Again(), Once(), exported] enddef def Once(): string *************** *** 1185,1199 **** g:loadCount = 0 source XReloaded assert_equal(1, g:loadCount) ! assert_equal(['first', 'yes', 'again', 'once'], g:Values()) source XReloaded assert_equal(2, g:loadCount) ! assert_equal(['init', 'yes', 'again', 'once'], g:Values()) source XReloaded assert_equal(3, g:loadCount) ! assert_equal(['init', 'yes', 'again', 'once'], g:Values()) delete('Xreloaded') delfunc g:Values unlet g:loadCount enddef --- 1201,1216 ---- g:loadCount = 0 source XReloaded assert_equal(1, g:loadCount) ! assert_equal(['first', 'yes', 'again', 'once', 'thexport'], g:Values()) source XReloaded assert_equal(2, g:loadCount) ! assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values()) source XReloaded assert_equal(3, g:loadCount) ! assert_equal(['init', 'yes', 'again', 'once', 'thexport'], g:Values()) delete('Xreloaded') + delete('XExportReload') delfunc g:Values unlet g:loadCount enddef *************** *** 2762,2767 **** --- 2779,2795 ---- enddef def Test_source_vim9_from_legacy() + var vim9_lines =<< trim END + vim9script + var local = 'local' + g:global = 'global' + export var exported = 'exported' + export def GetText(): string + return 'text' + enddef + END + writefile(vim9_lines, 'Xvim9_script.vim') + var legacy_lines =<< trim END source Xvim9_script.vim *************** *** 2783,2801 **** END writefile(legacy_lines, 'Xlegacy_script.vim') - var vim9_lines =<< trim END - vim9script - var local = 'local' - g:global = 'global' - export var exported = 'exported' - export def GetText(): string - return 'text' - enddef - END - writefile(vim9_lines, 'Xvim9_script.vim') - source Xlegacy_script.vim - assert_equal('global', g:global) unlet g:global --- 2811,2817 ---- *** ../vim-8.2.2224/src/version.c 2020-12-26 20:09:11.286465244 +0100 --- src/version.c 2020-12-27 13:38:27.079292899 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2225, /**/ -- Tips for aliens in New York: Land anywhere. Central Park, anywhere. No one will care or indeed even notice. -- Douglas Adams, "The Hitchhiker's Guide to the Galaxy" /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///