Mercurial > vim
comparison 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 |
comparison
equal
deleted
inserted
replaced
28216:b6a02697f304 | 28217:662d2d5db9a6 |
---|---|
120 } | 120 } |
121 | 121 |
122 /* | 122 /* |
123 * Create a new list from "count" items at the bottom of the stack. | 123 * Create a new list from "count" items at the bottom of the stack. |
124 * When "count" is zero an empty list is added to the stack. | 124 * When "count" is zero an empty list is added to the stack. |
125 * When "count" is -1 a NULL list is added to the stack. | |
125 */ | 126 */ |
126 static int | 127 static int |
127 exe_newlist(int count, ectx_T *ectx) | 128 exe_newlist(int count, ectx_T *ectx) |
128 { | 129 { |
129 list_T *list = list_alloc_with_items(count); | 130 list_T *list = NULL; |
130 int idx; | 131 int idx; |
131 typval_T *tv; | 132 typval_T *tv; |
132 | 133 |
133 if (list == NULL) | 134 if (count >= 0) |
134 return FAIL; | 135 { |
135 for (idx = 0; idx < count; ++idx) | 136 list = list_alloc_with_items(count); |
136 list_set_item(list, idx, STACK_TV_BOT(idx - count)); | 137 if (list == NULL) |
138 return FAIL; | |
139 for (idx = 0; idx < count; ++idx) | |
140 list_set_item(list, idx, STACK_TV_BOT(idx - count)); | |
141 } | |
137 | 142 |
138 if (count > 0) | 143 if (count > 0) |
139 ectx->ec_stack.ga_len -= count - 1; | 144 ectx->ec_stack.ga_len -= count - 1; |
145 else if (GA_GROW_FAILS(&ectx->ec_stack, 1)) | |
146 { | |
147 list_unref(list); | |
148 return FAIL; | |
149 } | |
150 else | |
151 ++ectx->ec_stack.ga_len; | |
152 tv = STACK_TV_BOT(-1); | |
153 tv->v_type = VAR_LIST; | |
154 tv->vval.v_list = list; | |
155 if (list != NULL) | |
156 ++list->lv_refcount; | |
157 return OK; | |
158 } | |
159 | |
160 /* | |
161 * Implementation of ISN_NEWDICT. | |
162 * Returns FAIL on total failure, MAYBE on error. | |
163 */ | |
164 static int | |
165 exe_newdict(int count, ectx_T *ectx) | |
166 { | |
167 dict_T *dict = NULL; | |
168 dictitem_T *item; | |
169 char_u *key; | |
170 int idx; | |
171 typval_T *tv; | |
172 | |
173 if (count >= 0) | |
174 { | |
175 dict = dict_alloc(); | |
176 if (unlikely(dict == NULL)) | |
177 return FAIL; | |
178 for (idx = 0; idx < count; ++idx) | |
179 { | |
180 // have already checked key type is VAR_STRING | |
181 tv = STACK_TV_BOT(2 * (idx - count)); | |
182 // check key is unique | |
183 key = tv->vval.v_string == NULL | |
184 ? (char_u *)"" : tv->vval.v_string; | |
185 item = dict_find(dict, key, -1); | |
186 if (item != NULL) | |
187 { | |
188 semsg(_(e_duplicate_key_in_dicitonary), key); | |
189 dict_unref(dict); | |
190 return MAYBE; | |
191 } | |
192 item = dictitem_alloc(key); | |
193 clear_tv(tv); | |
194 if (unlikely(item == NULL)) | |
195 { | |
196 dict_unref(dict); | |
197 return FAIL; | |
198 } | |
199 item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); | |
200 item->di_tv.v_lock = 0; | |
201 if (dict_add(dict, item) == FAIL) | |
202 { | |
203 // can this ever happen? | |
204 dict_unref(dict); | |
205 return FAIL; | |
206 } | |
207 } | |
208 } | |
209 | |
210 if (count > 0) | |
211 ectx->ec_stack.ga_len -= 2 * count - 1; | |
140 else if (GA_GROW_FAILS(&ectx->ec_stack, 1)) | 212 else if (GA_GROW_FAILS(&ectx->ec_stack, 1)) |
141 return FAIL; | 213 return FAIL; |
142 else | 214 else |
143 ++ectx->ec_stack.ga_len; | 215 ++ectx->ec_stack.ga_len; |
144 tv = STACK_TV_BOT(-1); | 216 tv = STACK_TV_BOT(-1); |
145 tv->v_type = VAR_LIST; | 217 tv->v_type = VAR_DICT; |
146 tv->vval.v_list = list; | 218 tv->v_lock = 0; |
147 ++list->lv_refcount; | 219 tv->vval.v_dict = dict; |
220 if (dict != NULL) | |
221 ++dict->dv_refcount; | |
148 return OK; | 222 return OK; |
149 } | 223 } |
150 | 224 |
151 /* | 225 /* |
152 * If debug_tick changed check if "ufunc" has a breakpoint and update | 226 * If debug_tick changed check if "ufunc" has a breakpoint and update |
3355 break; | 3429 break; |
3356 | 3430 |
3357 // create a dict from items on the stack | 3431 // create a dict from items on the stack |
3358 case ISN_NEWDICT: | 3432 case ISN_NEWDICT: |
3359 { | 3433 { |
3360 int count = iptr->isn_arg.number; | 3434 int res; |
3361 dict_T *dict = dict_alloc(); | 3435 |
3362 dictitem_T *item; | 3436 SOURCING_LNUM = iptr->isn_lnum; |
3363 char_u *key; | 3437 res = exe_newdict(iptr->isn_arg.number, ectx); |
3364 int idx; | 3438 if (res == FAIL) |
3365 | |
3366 if (unlikely(dict == NULL)) | |
3367 goto theend; | 3439 goto theend; |
3368 for (idx = 0; idx < count; ++idx) | 3440 if (res == MAYBE) |
3369 { | 3441 goto on_error; |
3370 // have already checked key type is VAR_STRING | |
3371 tv = STACK_TV_BOT(2 * (idx - count)); | |
3372 // check key is unique | |
3373 key = tv->vval.v_string == NULL | |
3374 ? (char_u *)"" : tv->vval.v_string; | |
3375 item = dict_find(dict, key, -1); | |
3376 if (item != NULL) | |
3377 { | |
3378 SOURCING_LNUM = iptr->isn_lnum; | |
3379 semsg(_(e_duplicate_key_in_dicitonary), key); | |
3380 dict_unref(dict); | |
3381 goto on_error; | |
3382 } | |
3383 item = dictitem_alloc(key); | |
3384 clear_tv(tv); | |
3385 if (unlikely(item == NULL)) | |
3386 { | |
3387 dict_unref(dict); | |
3388 goto theend; | |
3389 } | |
3390 item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); | |
3391 item->di_tv.v_lock = 0; | |
3392 if (dict_add(dict, item) == FAIL) | |
3393 { | |
3394 // can this ever happen? | |
3395 dict_unref(dict); | |
3396 goto theend; | |
3397 } | |
3398 } | |
3399 | |
3400 if (count > 0) | |
3401 ectx->ec_stack.ga_len -= 2 * count - 1; | |
3402 else if (GA_GROW_FAILS(&ectx->ec_stack, 1)) | |
3403 goto theend; | |
3404 else | |
3405 ++ectx->ec_stack.ga_len; | |
3406 tv = STACK_TV_BOT(-1); | |
3407 tv->v_type = VAR_DICT; | |
3408 tv->v_lock = 0; | |
3409 tv->vval.v_dict = dict; | |
3410 ++dict->dv_refcount; | |
3411 } | 3442 } |
3412 break; | 3443 break; |
3413 | 3444 |
3414 // create a partial with NULL value | 3445 // create a partial with NULL value |
3415 case ISN_NEWPARTIAL: | 3446 case ISN_NEWPARTIAL: |