changeset 33543:1299280b12db v9.0.2020

patch 9.0.2020: Vim9: islocked() needs more work Commit: https://github.com/vim/vim/commit/0f058d13206665bad37c7d42834cfa0075f50239 Author: Ernie Rael <errael@raelity.com> Date: Sat Oct 14 11:25:04 2023 +0200 patch 9.0.2020: Vim9: islocked() needs more work 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>
author Christian Brabandt <cb@256bit.org>
date Sat, 14 Oct 2023 11:30:10 +0200
parents c1e81b86082c
children 8d846b2c5159
files src/eval.c src/evalfunc.c src/structs.h src/version.c
diffstat 4 files changed, 38 insertions(+), 82 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -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)
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -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)
-{
-    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.
+fix_variable_reference_lval_root(lval_root_T *root, char_u *name)
+{
+
+    // 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 (!root->lr_sync_root)	// not object member, try class member
+	if (STRNCMP("this.", name, 5) == 0 ||STRCMP("this", name) == 0)
+	    found_member = TRUE;
+    }
+    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)
-	{
-	    // 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;
-	    }
-	}
-    }
-    if (!root->lr_sync_root)
+	int idx = class_member_idx(root->lr_cl_exec, name, end - name);
+	if (idx >= 0)
+	{
+	    // 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 (!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 *
     {
 	// 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;
--- a/src/structs.h
+++ b/src/structs.h
@@ -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
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2020,
+/**/
     2019,
 /**/
     2018,