# HG changeset patch # User Christian Brabandt # Date 1697275810 -7200 # Node ID 1299280b12db0a46eff49b932566a00f2f405027 # Parent c1e81b86082c70aefcd19069f2d49db1caddc01b patch 9.0.2020: Vim9: islocked() needs more work Commit: https://github.com/vim/vim/commit/0f058d13206665bad37c7d42834cfa0075f50239 Author: Ernie Rael 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 Co-authored-by: Ernie Rael diff --git a/src/eval.c b/src/eval.c --- 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) diff --git a/src/evalfunc.c b/src/evalfunc.c --- 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; diff --git a/src/structs.h b/src/structs.h --- 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 diff --git a/src/version.c b/src/version.c --- 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,