]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.2020: Vim9: islocked() needs more work v9.0.2020
authorErnie Rael <errael@raelity.com>
Sat, 14 Oct 2023 09:25:04 +0000 (11:25 +0200)
committerChristian Brabandt <cb@256bit.org>
Sat, 14 Oct 2023 09:25:04 +0000 (11:25 +0200)
Problem:  Vim9: islocked() needs more work
Solution: rework islocked() and remove sync_root
          from get_lval()

closes: #13329

Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Ernie Rael <errael@raelity.com>
src/eval.c
src/evalfunc.c
src/structs.h
src/version.c

index 80ff5a3cbaf7100d7872ea104b2b0f3df1513739..46eec355722f538de6fc3c9183d7ecb1400f1502 100644 (file)
@@ -1187,7 +1187,6 @@ get_lval(
     char buf[80];
     ch_log(NULL, "LKVAR:    ...: GLV flags: %s",
                    flags_tostring(flags, glv_flag_strings, buf, sizeof(buf)));
-    int log_sync_root_key = FALSE;
 #endif
 
     // Clear everything in "lp".
@@ -1326,21 +1325,16 @@ get_lval(
        }
     }
 
-    int sync_root = FALSE;
-    if (vim9script && lval_root != NULL)
-    {
-       cl_exec = lval_root->lr_cl_exec;
-       sync_root = lval_root->lr_sync_root;
-    }
-
-    // Without [idx] or .key we are done, unless doing sync_root.
-    if (*p != '[' && *p != '.' && (*name == NUL || !sync_root))
+    // Without [idx] or .key we are done.
+    if (*p != '[' && *p != '.')
     {
        if (lval_root != NULL)
            fill_lval_from_lval_root(lp, lval_root);
        return p;
     }
 
+    if (vim9script && lval_root != NULL)
+       cl_exec = lval_root->lr_cl_exec;
     if (vim9script && lval_root != NULL && lval_root->lr_tv != NULL)
     {
        // using local variable
@@ -1375,7 +1369,7 @@ get_lval(
      */
     var1.v_type = VAR_UNKNOWN;
     var2.v_type = VAR_UNKNOWN;
-    while (*p == '[' || (*p == '.' && p[1] != '=' && p[1] != '.') || sync_root)
+    while (*p == '[' || (*p == '.' && p[1] != '=' && p[1] != '.'))
     {
        vartype_T v_type = lp->ll_tv->v_type;
 
@@ -1439,19 +1433,7 @@ get_lval(
        }
 
        len = -1;
-       if (sync_root)
-       {
-           // For example, the first token is a member variable name and
-           // lp->ll_tv is a class/object.
-           // Process it directly without looking for "[idx]" or ".name".
-           key = name;
-           sync_root = FALSE;  // only first time through
-#ifdef LOG_LOCKVAR
-           log_sync_root_key = TRUE;
-           ch_log(NULL, "LKVAR:    ... loop: name: %s, sync_root", name);
-#endif
-       }
-       else if (*p == '.')
+       if (*p == '.')
        {
            key = p + 1;
            for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len)
@@ -1543,15 +1525,11 @@ get_lval(
            ++p;
        }
 #ifdef LOG_LOCKVAR
-       if (log_sync_root_key)
-           ch_log(NULL, "LKVAR:    ... loop: p: %s, sync_root key: %s", p,
-                                                                       key);
-       else if (len == -1)
+       if (len == -1)
            ch_log(NULL, "LKVAR:    ... loop: p: %s, '[' key: %s", p,
                                empty1 ? ":" : (char*)tv_get_string(&var1));
        else
            ch_log(NULL, "LKVAR:    ... loop: p: %s, '.' key: %s", p, key);
-       log_sync_root_key = FALSE;
 #endif
 
        if (v_type == VAR_DICT)
index 85c64a23a28ff1b8f486734032163f2600d3a5ed..f9b81c6054c2d0320225dca66c7293ca84574a88 100644 (file)
@@ -7325,64 +7325,48 @@ free_lval_root(lval_root_T *root)
 
 /*
  * This is used if executing in a method, the argument string is a
- * variable/item expr/reference. If it starts with a potential class/object
- * variable then return OK, may get later errors in get_lval.
+ * variable/item expr/reference. It may start with a potential class/object
+ * variable.
  *
- * Adjust "root" as needed. Note that name may change (for example to skip
- * "this") and is returned. lr_tv may be changed or freed.
+ * Adjust "root" as needed; lr_tv may be changed or freed.
  *
  * Always returns OK.
  * Free resources and return FAIL if the root should not be used. Otherwise OK.
  */
 
     static int
-fix_variable_reference_lval_root(lval_root_T *root, char_u **p_name)
+fix_variable_reference_lval_root(lval_root_T *root, char_u *name)
 {
-    char_u     *name = *p_name;
-    char_u     *end;
-    dictitem_T *di;
 
-    // Only set lr_sync_root and lr_tv if the name is an object/class
-    // reference: object ("this.") or class because name is class variable.
+    // Check if lr_tv is the name of an object/class reference: name start with
+    // "this" or name is class variable. Clear lr_tv if neither.
+    int found_member = FALSE;
     if (root->lr_tv->v_type == VAR_OBJECT)
     {
-       if (STRNCMP("this.", name, 5) == 0)
-       {
-           name += 5;
-               root->lr_sync_root = TRUE;
-       }
-       else if (STRCMP("this", name) == 0)
-       {
-           name += 4;
-           root->lr_sync_root = TRUE;
-       }
+       if (STRNCMP("this.", name, 5) == 0 ||STRCMP("this", name) == 0)
+           found_member = TRUE;
     }
-    if (!root->lr_sync_root)   // not object member, try class member
+    if (!found_member) // not object member, try class member
     {
        // Explicitly check if the name is a class member.
        // If it's not then do nothing.
+       char_u  *end;
        for (end = name; ASCII_ISALNUM(*end) || *end == '_'; ++end)
            ;
-       if (class_member_lookup(root->lr_cl_exec, name, end - name, NULL)
-                                                                   != NULL)
+       int idx = class_member_idx(root->lr_cl_exec, name, end - name);
+       if (idx >= 0)
        {
-           // Using a class, so reference the class tv.
-           di = find_var(root->lr_cl_exec->class_name, NULL, FALSE);
-           if (di != NULL)
-           {
-               // replace the lr_tv
-               clear_tv(root->lr_tv);
-               copy_tv(&di->di_tv, root->lr_tv);
-               root->lr_sync_root = TRUE;
-           }
+           // A class variable, replace lr_tv with it
+           clear_tv(root->lr_tv);
+           copy_tv(&root->lr_cl_exec->class_members_tv[idx], root->lr_tv);
+           found_member = TRUE;
        }
     }
-    if (!root->lr_sync_root)
+    if (!found_member)
     {
        free_tv(root->lr_tv);
        root->lr_tv = NULL;         // Not a member variable
     }
-    *p_name = name;
     // If FAIL, then must free_lval_root(root);
     return OK;
 }
@@ -7415,12 +7399,8 @@ f_islocked(typval_T *argvars, typval_T *rettv)
     {
        // Almost always produces a valid lval_root since lr_cl_exec is used
        // for access verification, lr_tv may be set to NULL.
-       char_u *tname = name;
-       if (fix_variable_reference_lval_root(&aroot, &tname) == OK)
-       {
-           name = tname;
+       if (fix_variable_reference_lval_root(&aroot, name) == OK)
            root = &aroot;
-       }
     }
 
     lval_root_T        *lval_root_save = lval_root;
index a221a0406dc7a561e4e67536d8cf515fbfa6a31d..3f461f8514073997ba935833cdc60c305c3aa53b 100644 (file)
@@ -4605,16 +4605,12 @@ typedef struct lval_S
 } lval_T;
 
 /**
- * This may be used to specify the base typval that get_lval() uses when
- * following a chain, for example a[idx1][idx2].
- * The lr_sync_root flags signals get_lval that the first time through
- * the indexing loop, skip handling  '.' and '[idx]'.
+ * This specifies optional parameters for get_lval(). Arguments may be NULL.
  */
 typedef struct lval_root_S {
-    typval_T   *lr_tv;
-    class_T    *lr_cl_exec;    // executing class for access checking
-    int                lr_is_arg;
-    int                lr_sync_root;
+    typval_T   *lr_tv;         // Base typval.
+    class_T    *lr_cl_exec;    // Executing class for access checking.
+    int                lr_is_arg;      // name is an arg (not a member).
 } lval_root_T;
 
 // Structure used to save the current state.  Used when executing Normal mode
index 9147441a40fccd4b698b5e9fd9f9311a431a30c0..afcdadfbb194471e577215cc98fd6b0ebef1b76e 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2020,
 /**/
     2019,
 /**/