diff options
author | Ernie Rael <errael@raelity.com> | 2023-10-11 21:35:11 +0200 |
---|---|---|
committer | Christian Brabandt <cb@256bit.org> | 2023-10-11 21:38:24 +0200 |
commit | 4c8da025ef8140168b7a09d9fe922ce4bb40f19d (patch) | |
tree | 73571eb4b3ba86ed7a2f00c9897796bfc92111d0 /src/eval.c | |
parent | c97b3febc82c1ccacf5f328ed0bd81c8b850e97d (diff) |
patch 9.0.2015: Vim9: does not handle islocked() from a method correctlyv9.0.2015
Problem: Vim9: does not handle islocked() from a method correctly
Solution: Handle islocked() builtin from a method.
- Setup `lval_root` from `f_islocked()`.
- Add function `fill_exec_lval_root()` to get info about executing method.
- `sync_root` added in get_lval to handle method member access.
- Conservative approach to reference counting.
closes: #13309
Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Ernie Rael <errael@raelity.com>
Diffstat (limited to 'src/eval.c')
-rw-r--r-- | src/eval.c | 79 |
1 files changed, 63 insertions, 16 deletions
diff --git a/src/eval.c b/src/eval.c index 8b26eb189f..4da6246ace 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1050,11 +1050,14 @@ flag_string_T glv_flag_strings[] = { * execute_instructions: ISN_LOCKUNLOCK - sets lval_root from stack. */ static void -get_lval_root(lval_T *lp, lval_root_T *lr) +fill_lval_from_lval_root(lval_T *lp, lval_root_T *lr) { #ifdef LOG_LOCKVAR - ch_log(NULL, "LKVAR: get_lval_root(): name %s", lp->ll_name); + ch_log(NULL, "LKVAR: fill_lval_from_lval_root(): name %s, tv %p", + lp->ll_name, (void*)lr->lr_tv); #endif + if (lr->lr_tv == NULL) + return; if (!lr->lr_is_arg && lr->lr_tv->v_type == VAR_CLASS) { if (lr->lr_tv->vval.v_class != NULL) @@ -1177,15 +1180,14 @@ get_lval( #ifdef LOG_LOCKVAR if (lval_root == NULL) - ch_log(NULL, - "LKVAR: get_lval(): name %s, lval_root (nil)", name); + ch_log(NULL, "LKVAR: get_lval(): name: %s, lval_root (nil)", name); else - ch_log(NULL, - "LKVAR: get_lval(): name %s, lr_tv %p lr_is_arg %d", - name, (void*)lval_root->lr_tv, lval_root->lr_is_arg); + ch_log(NULL, "LKVAR: get_lval(): name: %s, lr_tv %p lr_is_arg %d", + name, (void*)lval_root->lr_tv, lval_root->lr_is_arg); char buf[80]; - ch_log(NULL, "LKVAR: ...: GLV flags %s", + 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". @@ -1324,20 +1326,26 @@ get_lval( } } - // Without [idx] or .key we are done. - if ((*p != '[' && *p != '.')) + 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)) { if (lval_root != NULL) - get_lval_root(lp, lval_root); + fill_lval_from_lval_root(lp, lval_root); return p; } - if (vim9script && lval_root != NULL) + if (vim9script && lval_root != NULL && lval_root->lr_tv != NULL) { // using local variable lp->ll_tv = lval_root->lr_tv; v = NULL; - cl_exec = lval_root->lr_cl_exec; } else { @@ -1367,7 +1375,7 @@ get_lval( */ var1.v_type = VAR_UNKNOWN; var2.v_type = VAR_UNKNOWN; - while (*p == '[' || (*p == '.' && p[1] != '=' && p[1] != '.')) + while (*p == '[' || (*p == '.' && p[1] != '=' && p[1] != '.') || sync_root) { vartype_T v_type = lp->ll_tv->v_type; @@ -1407,6 +1415,10 @@ get_lval( emsg(_(e_slice_must_come_last)); return NULL; } +#ifdef LOG_LOCKVAR + ch_log(NULL, "LKVAR: get_lval() loop: p: %s, type: %s", p, + vartype_name(v_type)); +#endif if (vim9script && lp->ll_valtype == NULL && v != NULL @@ -1417,11 +1429,29 @@ get_lval( // Vim9 script local variable: get the type if (sv != NULL) + { lp->ll_valtype = sv->sv_type; +#ifdef LOG_LOCKVAR + ch_log(NULL, "LKVAR: ... loop: vim9 assign type: %s", + vartype_name(lp->ll_valtype->tt_type)); +#endif + } } len = -1; - if (*p == '.') + 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 == '.') { key = p + 1; for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; ++len) @@ -1512,6 +1542,17 @@ get_lval( // Skip to past ']'. ++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) + 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) { @@ -1700,8 +1741,14 @@ get_lval( lp->ll_list = NULL; class_T *cl; - if (v_type == VAR_OBJECT && lp->ll_tv->vval.v_object != NULL) + if (v_type == VAR_OBJECT) { + if (lp->ll_tv->vval.v_object == NULL) + { + if (!quiet) + emsg(_(e_using_null_object)); + return NULL; + } cl = lp->ll_tv->vval.v_object->obj_class; lp->ll_object = lp->ll_tv->vval.v_object; } |