Mercurial > vim
diff src/vim9execute.c @ 28217:662d2d5db9a6
patch 8.2.4634: Vim9: cannot initialize a variable to null_list
Commit: https://github.com/vim/vim/commit/ec15b1cfdc5faadb529dedda58adf7fc98c839ed
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Mar 27 16:29:53 2022 +0100
patch 8.2.4634: Vim9: cannot initialize a variable to null_list
Problem: Vim9: cannot initialize a variable to null_list.
Solution: Give negative count to NEWLIST. (closes https://github.com/vim/vim/issues/10027)
Also fix inconsistencies in comparing with null values.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 27 Mar 2022 17:30:04 +0200 |
parents | 088d8dc22045 |
children | 66b245d84f37 |
line wrap: on
line diff
--- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -122,29 +122,103 @@ ufunc_argcount(ufunc_T *ufunc) /* * Create a new list from "count" items at the bottom of the stack. * When "count" is zero an empty list is added to the stack. + * When "count" is -1 a NULL list is added to the stack. */ static int exe_newlist(int count, ectx_T *ectx) { - list_T *list = list_alloc_with_items(count); + list_T *list = NULL; int idx; typval_T *tv; - if (list == NULL) - return FAIL; - for (idx = 0; idx < count; ++idx) - list_set_item(list, idx, STACK_TV_BOT(idx - count)); + if (count >= 0) + { + list = list_alloc_with_items(count); + if (list == NULL) + return FAIL; + for (idx = 0; idx < count; ++idx) + list_set_item(list, idx, STACK_TV_BOT(idx - count)); + } if (count > 0) ectx->ec_stack.ga_len -= count - 1; else if (GA_GROW_FAILS(&ectx->ec_stack, 1)) + { + list_unref(list); + return FAIL; + } + else + ++ectx->ec_stack.ga_len; + tv = STACK_TV_BOT(-1); + tv->v_type = VAR_LIST; + tv->vval.v_list = list; + if (list != NULL) + ++list->lv_refcount; + return OK; +} + +/* + * Implementation of ISN_NEWDICT. + * Returns FAIL on total failure, MAYBE on error. + */ + static int +exe_newdict(int count, ectx_T *ectx) +{ + dict_T *dict = NULL; + dictitem_T *item; + char_u *key; + int idx; + typval_T *tv; + + if (count >= 0) + { + dict = dict_alloc(); + if (unlikely(dict == NULL)) + return FAIL; + for (idx = 0; idx < count; ++idx) + { + // have already checked key type is VAR_STRING + tv = STACK_TV_BOT(2 * (idx - count)); + // check key is unique + key = tv->vval.v_string == NULL + ? (char_u *)"" : tv->vval.v_string; + item = dict_find(dict, key, -1); + if (item != NULL) + { + semsg(_(e_duplicate_key_in_dicitonary), key); + dict_unref(dict); + return MAYBE; + } + item = dictitem_alloc(key); + clear_tv(tv); + if (unlikely(item == NULL)) + { + dict_unref(dict); + return FAIL; + } + item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); + item->di_tv.v_lock = 0; + if (dict_add(dict, item) == FAIL) + { + // can this ever happen? + dict_unref(dict); + return FAIL; + } + } + } + + if (count > 0) + ectx->ec_stack.ga_len -= 2 * count - 1; + else if (GA_GROW_FAILS(&ectx->ec_stack, 1)) return FAIL; else ++ectx->ec_stack.ga_len; tv = STACK_TV_BOT(-1); - tv->v_type = VAR_LIST; - tv->vval.v_list = list; - ++list->lv_refcount; + tv->v_type = VAR_DICT; + tv->v_lock = 0; + tv->vval.v_dict = dict; + if (dict != NULL) + ++dict->dv_refcount; return OK; } @@ -3357,57 +3431,14 @@ exec_instructions(ectx_T *ectx) // create a dict from items on the stack case ISN_NEWDICT: { - int count = iptr->isn_arg.number; - dict_T *dict = dict_alloc(); - dictitem_T *item; - char_u *key; - int idx; - - if (unlikely(dict == NULL)) + int res; + + SOURCING_LNUM = iptr->isn_lnum; + res = exe_newdict(iptr->isn_arg.number, ectx); + if (res == FAIL) goto theend; - for (idx = 0; idx < count; ++idx) - { - // have already checked key type is VAR_STRING - tv = STACK_TV_BOT(2 * (idx - count)); - // check key is unique - key = tv->vval.v_string == NULL - ? (char_u *)"" : tv->vval.v_string; - item = dict_find(dict, key, -1); - if (item != NULL) - { - SOURCING_LNUM = iptr->isn_lnum; - semsg(_(e_duplicate_key_in_dicitonary), key); - dict_unref(dict); - goto on_error; - } - item = dictitem_alloc(key); - clear_tv(tv); - if (unlikely(item == NULL)) - { - dict_unref(dict); - goto theend; - } - item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); - item->di_tv.v_lock = 0; - if (dict_add(dict, item) == FAIL) - { - // can this ever happen? - dict_unref(dict); - goto theend; - } - } - - if (count > 0) - ectx->ec_stack.ga_len -= 2 * count - 1; - else if (GA_GROW_FAILS(&ectx->ec_stack, 1)) - goto theend; - else - ++ectx->ec_stack.ga_len; - tv = STACK_TV_BOT(-1); - tv->v_type = VAR_DICT; - tv->v_lock = 0; - tv->vval.v_dict = dict; - ++dict->dv_refcount; + if (res == MAYBE) + goto on_error; } break;