Patch 8.2.0312
Problem:    Vim9: insufficient script tests.
Solution:   Add more tests.  Make "import * as Name" work.
Files:      src/testdir/test_vim9_script.vim, src/vim9script.c,
            src/proto/vim9script.pro, src/vim9compile.c


*** ../vim-8.2.0311/src/testdir/test_vim9_script.vim    2020-02-23 
18:08:29.463897252 +0100
--- src/testdir/test_vim9_script.vim    2020-02-23 21:14:47.294383000 +0100
***************
*** 331,336 ****
--- 331,358 ----
    unlet g:imported_func
    unlet g:imported_name g:imported_name_appended
    delete('Ximport.vim')
+ 
+   let import_star_as_lines =<< trim END
+     vim9script
+     import * as Export from './Xexport.vim'
+     def UseExport()
+       g:imported = Export.exported
+     enddef
+     UseExport()
+   END
+   writefile(import_star_as_lines, 'Ximport.vim')
+   source Ximport.vim
+   assert_equal(9876, g:imported)
+ 
+   let import_star_lines =<< trim END
+     vim9script
+     import * from './Xexport.vim'
+     g:imported = exported
+   END
+   writefile(import_star_lines, 'Ximport.vim')
+   assert_fails('source Ximport.vim', 'E1045:')
+ 
+   delete('Ximport.vim')
    delete('Xexport.vim')
  
    " Check that in a Vim9 script 'cpo' is set to the Vim default.
***************
*** 352,357 ****
--- 374,380 ----
    CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
    CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
    CheckScriptFailure(['export let some = 123'], 'E1042:')
+   CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1042:')
    CheckScriptFailure(['vim9script', 'export let g:some'], 'E1044:')
    CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
  
*** ../vim-8.2.0311/src/vim9script.c    2020-01-28 23:13:39.458166365 +0100
--- src/vim9script.c    2020-02-23 19:53:48.406528554 +0100
***************
*** 151,156 ****
--- 151,238 ----
  }
  
  /*
+  * Find an exported item in "sid" matching the name at "*argp".
+  * When it is a variable return the index.
+  * When it is a user function return "*ufunc".
+  * When not found returns -1 and "*ufunc" is NULL.
+  */
+     int
+ find_exported(
+       int         sid,
+       char_u      **argp,
+       int         *name_len,
+       ufunc_T     **ufunc,
+       type_T      **type)
+ {
+     char_u    *name = *argp;
+     char_u    *arg = *argp;
+     int               cc;
+     int               idx = -1;
+     svar_T    *sv;
+     scriptitem_T *script = SCRIPT_ITEM(sid);
+ 
+     // isolate one name
+     while (eval_isnamec1(*arg))
+       ++arg;
+     *name_len = (int)(arg - name);
+ 
+     // find name in "script"
+     // TODO: also find script-local user function
+     cc = *arg;
+     *arg = NUL;
+     idx = get_script_item_idx(sid, name, FALSE);
+     if (idx >= 0)
+     {
+       sv = ((svar_T *)script->sn_var_vals.ga_data) + idx;
+       if (!sv->sv_export)
+       {
+           semsg(_("E1049: Item not exported in script: %s"), name);
+           *arg = cc;
+           return -1;
+       }
+       *type = sv->sv_type;
+       *ufunc = NULL;
+     }
+     else
+     {
+       char_u  buffer[200];
+       char_u  *funcname;
+ 
+       // it could be a user function.
+       if (STRLEN(name) < sizeof(buffer) - 10)
+           funcname = buffer;
+       else
+       {
+           funcname = alloc(STRLEN(name) + 10);
+           if (funcname == NULL)
+           {
+               *arg = cc;
+               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, NULL);
+       if (funcname != buffer)
+           vim_free(funcname);
+ 
+       if (*ufunc == NULL)
+       {
+           semsg(_("E1048: Item not found in script: %s"), name);
+           *arg = cc;
+           return -1;
+       }
+     }
+     *arg = cc;
+     arg = skipwhite(arg);
+     *argp = arg;
+ 
+     return idx;
+ }
+ 
+ /*
   * Handle an ":import" command and add the resulting imported_T to "gap", when
   * not NULL, or script "import_sid" sn_imports.
   * Returns a pointer to after the command or NULL in case of failure
***************
*** 289,296 ****
      }
      else
      {
-       scriptitem_T *script = SCRIPT_ITEM(sid);
- 
        arg = arg_start;
        if (*arg == '{')
            arg = skipwhite(arg + 1);
--- 371,376 ----
***************
*** 298,365 ****
        {
            char_u      *name = arg;
            int         name_len;
-           int         cc;
            int         idx;
-           svar_T      *sv;
            imported_T  *imported;
!           ufunc_T     *ufunc;
! 
!           // isolate one name
!           while (eval_isnamec1(*arg))
!               ++arg;
!           name_len = (int)(arg - name);
  
!           // find name in "script"
!           // TODO: also find script-local user function
!           cc = *arg;
!           *arg = NUL;
!           idx = get_script_item_idx(sid, name, FALSE);
!           if (idx >= 0)
!           {
!               sv = ((svar_T *)script->sn_var_vals.ga_data) + idx;
!               if (!sv->sv_export)
!               {
!                   semsg(_("E1049: Item not exported in script: %s"), name);
!                   *arg = cc;
!                   return NULL;
!               }
!               ufunc = NULL;
!           }
!           else
!           {
!               char_u  buffer[200];
!               char_u  *funcname;
  
!               // it could be a user function.
!               if (STRLEN(name) < sizeof(buffer) - 10)
!                   funcname = buffer;
!               else
!               {
!                   funcname = alloc(STRLEN(name) + 10);
!                   if (funcname == NULL)
!                   {
!                       *arg = cc;
!                       return NULL;
!                   }
!               }
!               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, NULL);
!               if (funcname != buffer)
!                   vim_free(funcname);
! 
!               if (ufunc == NULL)
!               {
!                   semsg(_("E1048: Item not found in script: %s"), name);
!                   *arg = cc;
!                   return NULL;
!               }
!               sv = NULL;
!           }
!           *arg = cc;
!           arg = skipwhite(arg);
  
            imported = new_imported(gap != NULL ? gap
                                       : &SCRIPT_ITEM(import_sid)->sn_imports);
--- 378,392 ----
        {
            char_u      *name = arg;
            int         name_len;
            int         idx;
            imported_T  *imported;
!           ufunc_T     *ufunc = NULL;
!           type_T      *type;
  
!           idx = find_exported(sid, &arg, &name_len, &ufunc, &type);
  
!           if (idx < 0 && ufunc == NULL)
!               return NULL;
  
            imported = new_imported(gap != NULL ? gap
                                       : &SCRIPT_ITEM(import_sid)->sn_imports);
***************
*** 372,378 ****
            imported->imp_sid = sid;
            if (idx >= 0)
            {
!               imported->imp_type = sv->sv_type;
                imported->imp_var_vals_idx = idx;
            }
            else
--- 399,405 ----
            imported->imp_sid = sid;
            if (idx >= 0)
            {
!               imported->imp_type = type;
                imported->imp_var_vals_idx = idx;
            }
            else
*** ../vim-8.2.0311/src/proto/vim9script.pro    2020-01-26 15:52:33.023833239 
+0100
--- src/proto/vim9script.pro    2020-02-23 19:53:32.790584049 +0100
***************
*** 4,8 ****
  void ex_export(exarg_T *eap);
  void free_imports(int sid);
  void ex_import(exarg_T *eap);
! char_u *handle_import(char_u *arg_start, garray_T *gap, int sid);
  /* vim: set ft=c : */
--- 4,9 ----
  void ex_export(exarg_T *eap);
  void free_imports(int sid);
  void ex_import(exarg_T *eap);
! int find_exported(int sid, char_u **argp, int *name_len, ufunc_T **ufunc, 
type_T **type);
! char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid);
  /* vim: set ft=c : */
*** ../vim-8.2.0311/src/vim9compile.c   2020-02-22 18:36:18.608483742 +0100
--- src/vim9compile.c   2020-02-23 20:05:36.468265602 +0100
***************
*** 1522,1528 ****
   * Generate an instruction to load script-local variable "name".
   */
      static int
! compile_load_scriptvar(cctx_T *cctx, char_u *name)
  {
      scriptitem_T    *si = SCRIPT_ITEM(current_sctx.sc_sid);
      int                   idx = get_script_item_idx(current_sctx.sc_sid, 
name, FALSE);
--- 1522,1532 ----
   * Generate an instruction to load script-local variable "name".
   */
      static int
! compile_load_scriptvar(
!       cctx_T *cctx,
!       char_u *name,       // variable NUL terminated
!       char_u *start,      // start of variable
!       char_u **end)       // end of variable
  {
      scriptitem_T    *si = SCRIPT_ITEM(current_sctx.sc_sid);
      int                   idx = get_script_item_idx(current_sctx.sc_sid, 
name, FALSE);
***************
*** 1546,1556 ****
      import = find_imported(name, 0, cctx);
      if (import != NULL)
      {
!       // TODO: check this is a variable, not a function
!       generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
!               import->imp_sid,
!               import->imp_var_vals_idx,
!               import->imp_type);
        return OK;
      }
  
--- 1550,1589 ----
      import = find_imported(name, 0, cctx);
      if (import != NULL)
      {
!       if (import->imp_all)
!       {
!           char_u      *p = skipwhite(*end);
!           int         name_len;
!           ufunc_T     *ufunc;
!           type_T      *type;
! 
!           // Used "import * as Name", need to lookup the member.
!           if (*p != '.')
!           {
!               semsg(_("E1060: expected dot after name: %s"), start);
!               return FAIL;
!           }
!           ++p;
! 
!           idx = find_exported(import->imp_sid, &p, &name_len, &ufunc, &type);
!           // TODO: what if it is a function?
!           if (idx < 0)
!               return FAIL;
!           *end = p;
! 
!           generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
!                   import->imp_sid,
!                   idx,
!                   type);
!       }
!       else
!       {
!           // TODO: check this is a variable, not a function
!           generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
!                   import->imp_sid,
!                   import->imp_var_vals_idx,
!                   import->imp_type);
!       }
        return OK;
      }
  
***************
*** 1564,1573 ****
   * When "error" is FALSE do not give an error when not found.
   */
      static int
! compile_load(char_u **arg, char_u *end, cctx_T *cctx, int error)
  {
      type_T    *type;
      char_u    *name;
      int               res = FAIL;
  
      if (*(*arg + 1) == ':')
--- 1597,1607 ----
   * When "error" is FALSE do not give an error when not found.
   */
      static int
! compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
  {
      type_T    *type;
      char_u    *name;
+     char_u    *end = end_arg;
      int               res = FAIL;
  
      if (*(*arg + 1) == ':')
***************
*** 1589,1595 ****
        }
        else if (**arg == 's')
        {
!           res = compile_load_scriptvar(cctx, name);
        }
        else
        {
--- 1623,1629 ----
        }
        else if (**arg == 's')
        {
!           res = compile_load_scriptvar(cctx, name, NULL, NULL);
        }
        else
        {
***************
*** 1645,1651 ****
                else if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
                                                        == SCRIPT_VERSION_VIM9)
                    // in Vim9 script "var" can be script-local.
!                  res = compile_load_scriptvar(cctx, name);
            }
        }
        if (gen_load)
--- 1679,1685 ----
                else if (SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
                                                        == SCRIPT_VERSION_VIM9)
                    // in Vim9 script "var" can be script-local.
!                  res = compile_load_scriptvar(cctx, name, *arg, &end);
            }
        }
        if (gen_load)
***************
*** 3412,3418 ****
                    generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
                    break;
                case dest_script:
!                   compile_load_scriptvar(cctx, name + (name[1] == ':' ? 2 : 
0));
                    break;
                case dest_env:
                    // Include $ in the name here
--- 3446,3452 ----
                    generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
                    break;
                case dest_script:
!                   compile_load_scriptvar(cctx, name + (name[1] == ':' ? 2 : 
0), NULL, NULL);
                    break;
                case dest_env:
                    // Include $ in the name here
*** ../vim-8.2.0311/src/version.c       2020-02-23 18:08:29.463897252 +0100
--- src/version.c       2020-02-23 21:25:11.764786291 +0100
***************
*** 740,741 ****
--- 740,743 ----
  {   /* Add new patch number below this line */
+ /**/
+     312,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
109. You actually read -- and enjoy -- lists like this.

 /// 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/202002232026.01NKQL61019331%40masaka.moolenaar.net.

Raspunde prin e-mail lui