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<string>
!       return [s:reloaded, s:notReloaded, Again(), Once()]
      enddef
  
      def Once(): string
--- 1190,1196 ----
      var s:notReloaded = 'yes'
      s:reloaded = 'first'
      def g:Values(): list<string>
!       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 -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202012271240.0BRCeLCh4114390%40masaka.moolenaar.net.

Raspunde prin e-mail lui