Patch 8.2.2090
Problem:    Vim9: dict does not accept a key in quotes.
Solution:   Recognize a key in single or double quotes.
Files:      runtime/doc/vim9.txt, src/dict.c, src/proto/dict.pro,
            src/vim9compile.c, src/testdir/test_vim9_expr.vim


*** ../vim-8.2.2089/runtime/doc/vim9.txt        2020-11-19 18:53:15.184492586 
+0100
--- runtime/doc/vim9.txt        2020-12-04 19:03:01.619017804 +0100
***************
*** 433,451 ****
  Traditionally Vim has supported dictionary literals with a {} syntax: >
        let dict = {'key': value}
  
! Later it became clear that using a simple key name is very common, thus
! literally dictionaries were introduced in a backwards compatible way: >
        let dict = #{key: value}
  
! However, this #{} syntax is unlike any existing language.  As it appears that
! using a literaly key is much more common than using an expression, and
  considering that JavaScript uses this syntax, using the {} form for dictionary
! literals was considered a much more useful syntax.  In Vim9 script the {} form
  uses literal keys: >
        let dict = {key: value}
  
! In case an expression needs to be used for the key, square brackets can be
! used, just like in JavaScript: >
        let dict = {["key" .. nr]: value}
  
  
--- 436,460 ----
  Traditionally Vim has supported dictionary literals with a {} syntax: >
        let dict = {'key': value}
  
! Later it became clear that using a simple text key is very common, thus
! literal dictionaries were introduced in a backwards compatible way: >
        let dict = #{key: value}
  
! However, this #{} syntax is unlike any existing language.  As it turns out
! that using a literal key is much more common than using an expression, and
  considering that JavaScript uses this syntax, using the {} form for dictionary
! literals is considered a much more useful syntax.  In Vim9 script the {} form
  uses literal keys: >
        let dict = {key: value}
  
! This works for alphanumeric characters, underscore and dash.  If you want to
! use another character, use a single or double quoted string: >
!       let dict = {'key with space': value}
!       let dict = {"key\twith\ttabs": value}
!       let dict = {'': value}                  # empty key
! 
! In case the key needs to be an expression, square brackets can be used, just
! like in JavaScript: >
        let dict = {["key" .. nr]: value}
  
  
*** ../vim-8.2.2089/src/dict.c  2020-12-02 17:36:49.169409752 +0100
--- src/dict.c  2020-12-04 18:55:50.744441533 +0100
***************
*** 801,807 ****
   * Return FAIL when there is no valid key.
   */
      static int
! get_literal_key(char_u **arg, typval_T *tv)
  {
      char_u *p = skip_literal_key(*arg);
  
--- 801,807 ----
   * Return FAIL when there is no valid key.
   */
      static int
! get_literal_key_tv(char_u **arg, typval_T *tv)
  {
      char_u *p = skip_literal_key(*arg);
  
***************
*** 815,820 ****
--- 815,861 ----
  }
  
  /*
+  * Get a literal key for a Vim9 dict:
+  * {"name": value},
+  * {'name': value},
+  * {name: value} use "name" as a literal key
+  * Return the key in allocated memory or NULL in the case of an error.
+  * "arg" is advanced to just after the key.
+  */
+     char_u *
+ get_literal_key(char_u **arg)
+ {
+     char_u    *key;
+     char_u    *end;
+     typval_T  rettv;
+ 
+     if (**arg == '\'')
+     {
+       if (eval_lit_string(arg, &rettv, TRUE) == FAIL)
+           return NULL;
+       key = rettv.vval.v_string;
+     }
+     else if (**arg == '"')
+     {
+       if (eval_string(arg, &rettv, TRUE) == FAIL)
+           return NULL;
+       key = rettv.vval.v_string;
+     }
+     else
+     {
+       end = skip_literal_key(*arg);
+       if (end == *arg)
+       {
+           semsg(_(e_invalid_key_str), *arg);
+           return NULL;
+       }
+       key = vim_strnsave(*arg, end - *arg);
+       *arg = end;
+     }
+     return key;
+ }
+ 
+ /*
   * Allocate a variable for a Dictionary and fill it from "*arg".
   * "*arg" points to the "{".
   * "literal" is TRUE for #{key: val}
***************
*** 864,873 ****
      {
        int     has_bracket = vim9script && **arg == '[';
  
!       if (literal || (vim9script && !has_bracket))
        {
!           if (get_literal_key(arg, &tvkey) == FAIL)
                goto failret;
        }
        else
        {
--- 905,921 ----
      {
        int     has_bracket = vim9script && **arg == '[';
  
!       if (literal)
!       {
!           if (get_literal_key_tv(arg, &tvkey) == FAIL)
!               goto failret;
!       }
!       else if (vim9script && !has_bracket)
        {
!           tvkey.vval.v_string = get_literal_key(arg);
!           if (tvkey.vval.v_string == NULL)
                goto failret;
+           tvkey.v_type = VAR_STRING;
        }
        else
        {
*** ../vim-8.2.2089/src/proto/dict.pro  2020-12-02 17:36:49.169409752 +0100
--- src/proto/dict.pro  2020-12-04 18:52:02.145226267 +0100
***************
*** 34,39 ****
--- 34,40 ----
  varnumber_T dict_get_bool(dict_T *d, char_u *key, int def);
  char_u *dict2string(typval_T *tv, int copyID, int restore_copyID);
  char_u *skip_literal_key(char_u *key);
+ char_u *get_literal_key(char_u **arg);
  int eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal);
  void dict_extend(dict_T *d1, dict_T *d2, char_u *action);
  dictitem_T *dict_lookup(hashitem_T *hi);
*** ../vim-8.2.2089/src/vim9compile.c   2020-12-04 12:43:23.786385152 +0100
--- src/vim9compile.c   2020-12-04 18:56:02.592401563 +0100
***************
*** 3024,3049 ****
        if (**arg == '}')
            break;
  
!       // {name: value} uses "name" as a literal key and
!       // {[expr]: value} uses an evaluated key.
!       if (**arg != '[')
!       {
!           char_u  *end = skip_literal_key(*arg);
! 
!           if (end == *arg)
!           {
!               semsg(_(e_invalid_key_str), *arg);
!               return FAIL;
!           }
!           key = vim_strnsave(*arg, end - *arg);
!           if (generate_PUSHS(cctx, key) == FAIL)
!               return FAIL;
!           *arg = end;
!       }
!       else
        {
            isn_T       *isn;
  
            *arg = skipwhite(*arg + 1);
            if (compile_expr0(arg, cctx) == FAIL)
                return FAIL;
--- 3024,3034 ----
        if (**arg == '}')
            break;
  
!       if (**arg == '[')
        {
            isn_T       *isn;
  
+           // {[expr]: value} uses an evaluated key.
            *arg = skipwhite(*arg + 1);
            if (compile_expr0(arg, cctx) == FAIL)
                return FAIL;
***************
*** 3066,3071 ****
--- 3051,3067 ----
            }
            ++*arg;
        }
+       else
+       {
+           // {"name": value},
+           // {'name': value},
+           // {name: value} use "name" as a literal key
+           key = get_literal_key(arg);
+           if (key == NULL)
+               return FAIL;
+           if (generate_PUSHS(cctx, key) == FAIL)
+               return FAIL;
+       }
  
        // Check for duplicate keys, if using string keys.
        if (key != NULL)
*** ../vim-8.2.2089/src/testdir/test_vim9_expr.vim      2020-12-02 
17:36:49.173409740 +0100
--- src/testdir/test_vim9_expr.vim      2020-12-04 18:58:28.299914463 +0100
***************
*** 1930,1941 ****
  
        assert_equal(g:test_space_dict, {['']: 'empty', [' ']: 'space'})
        assert_equal(g:test_hash_dict, {one: 1, two: 2})
    END
    CheckDefAndScriptSuccess(lines)
   
    # legacy syntax doesn't work
    CheckDefFailure(["var x = #{key: 8}"], 'E1097:', 2)
-   CheckDefFailure(["var x = {'key': 8}"], 'E1014:', 1)
    CheckDefFailure(["var x = 'a' .. #{a: 1}"], 'E1097:', 2)
  
    CheckDefFailure(["var x = {a:8}"], 'E1069:', 1)
--- 1930,1942 ----
  
        assert_equal(g:test_space_dict, {['']: 'empty', [' ']: 'space'})
        assert_equal(g:test_hash_dict, {one: 1, two: 2})
+ 
+       assert_equal({['a a']: 1, ['b/c']: 2}, {'a a': 1, "b/c": 2})
    END
    CheckDefAndScriptSuccess(lines)
   
    # legacy syntax doesn't work
    CheckDefFailure(["var x = #{key: 8}"], 'E1097:', 2)
    CheckDefFailure(["var x = 'a' .. #{a: 1}"], 'E1097:', 2)
  
    CheckDefFailure(["var x = {a:8}"], 'E1069:', 1)
*** ../vim-8.2.2089/src/version.c       2020-12-04 18:09:50.648966590 +0100
--- src/version.c       2020-12-04 19:03:27.970932225 +0100
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     2090,
  /**/

-- 
ARTHUR: Go on, Bors, chop its head off.
BORS:   Right.  Silly little bleeder.  One rabbit stew coming up.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// 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/202012041812.0B4ICgLB579503%40masaka.moolenaar.net.

Raspunde prin e-mail lui