Mercurial > vim
comparison src/vim9compile.c @ 20275:350bb78345ba v8.2.0693
patch 8.2.0693: closure using argument not tested
Commit: https://github.com/vim/vim/commit/2fd4cd755c3e87e733b7363ac13e5c0fe0297a80
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun May 3 22:30:49 2020 +0200
patch 8.2.0693: closure using argument not tested
Problem: Closure using argument not tested.
Solution: Add a test, make it work.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 03 May 2020 22:45:03 +0200 |
parents | b69e30dc6e6a |
children | 49b50843e725 |
comparison
equal
deleted
inserted
replaced
20274:ffb9ba069032 | 20275:350bb78345ba |
---|---|
184 | 184 |
185 return NULL; | 185 return NULL; |
186 } | 186 } |
187 | 187 |
188 /* | 188 /* |
189 * Lookup an argument in the current function. | 189 * Lookup an argument in the current function and an enclosing function. |
190 * Returns the argument index or -1 if not found. | 190 * Returns the argument index in "idxp" |
191 */ | 191 * Returns the argument type in "type" |
192 static int | 192 * Sets "gen_load_outer" to TRUE if found in outer scope. |
193 lookup_arg(char_u *name, size_t len, cctx_T *cctx) | 193 * Returns OK when found, FAIL otherwise. |
194 */ | |
195 static int | |
196 lookup_arg( | |
197 char_u *name, | |
198 size_t len, | |
199 int *idxp, | |
200 type_T **type, | |
201 int *gen_load_outer, | |
202 cctx_T *cctx) | |
194 { | 203 { |
195 int idx; | 204 int idx; |
205 char_u *va_name; | |
196 | 206 |
197 if (len == 0) | 207 if (len == 0) |
198 return -1; | 208 return FAIL; |
199 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx) | 209 for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx) |
200 { | 210 { |
201 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx); | 211 char_u *arg = FUNCARG(cctx->ctx_ufunc, idx); |
202 | 212 |
203 if (STRNCMP(name, arg, len) == 0 && STRLEN(arg) == len) | 213 if (STRNCMP(name, arg, len) == 0 && arg[len] == NUL) |
204 return idx; | 214 { |
205 } | 215 if (idxp != NULL) |
206 return -1; | 216 { |
207 } | 217 // Arguments are located above the frame pointer. One further |
208 | 218 // if there is a vararg argument |
209 /* | 219 *idxp = idx - (cctx->ctx_ufunc->uf_args.ga_len |
210 * Lookup a vararg argument in the current function. | 220 + STACK_FRAME_SIZE) |
211 * Returns TRUE if there is a match. | 221 + (cctx->ctx_ufunc->uf_va_name != NULL ? -1 : 0); |
212 */ | 222 |
213 static int | 223 if (cctx->ctx_ufunc->uf_arg_types != NULL) |
214 lookup_vararg(char_u *name, size_t len, cctx_T *cctx) | 224 *type = cctx->ctx_ufunc->uf_arg_types[idx]; |
215 { | 225 else |
216 char_u *va_name = cctx->ctx_ufunc->uf_va_name; | 226 *type = &t_any; |
217 | 227 } |
218 return len > 0 && va_name != NULL | 228 return OK; |
219 && STRNCMP(name, va_name, len) == 0 && STRLEN(va_name) == len; | 229 } |
230 } | |
231 | |
232 va_name = cctx->ctx_ufunc->uf_va_name; | |
233 if (va_name != NULL | |
234 && STRNCMP(name, va_name, len) == 0 && va_name[len] == NUL) | |
235 { | |
236 if (idxp != NULL) | |
237 { | |
238 // varargs is always the last argument | |
239 *idxp = -STACK_FRAME_SIZE - 1; | |
240 *type = cctx->ctx_ufunc->uf_va_type; | |
241 } | |
242 return OK; | |
243 } | |
244 | |
245 if (cctx->ctx_outer != NULL) | |
246 { | |
247 // Lookup the name for an argument of the outer function. | |
248 if (lookup_arg(name, len, idxp, type, gen_load_outer, cctx->ctx_outer) | |
249 == OK) | |
250 { | |
251 *gen_load_outer = TRUE; | |
252 return OK; | |
253 } | |
254 } | |
255 | |
256 return FAIL; | |
220 } | 257 } |
221 | 258 |
222 /* | 259 /* |
223 * Lookup a variable in the current script. | 260 * Lookup a variable in the current script. |
224 * Returns OK or FAIL. | 261 * Returns OK or FAIL. |
1582 static lvar_T * | 1619 static lvar_T * |
1583 reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type) | 1620 reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type) |
1584 { | 1621 { |
1585 lvar_T *lvar; | 1622 lvar_T *lvar; |
1586 | 1623 |
1587 if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx)) | 1624 if (lookup_arg(name, len, NULL, NULL, NULL, cctx) == OK) |
1588 { | 1625 { |
1589 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len); | 1626 emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len); |
1590 return NULL; | 1627 return NULL; |
1591 } | 1628 } |
1592 | 1629 |
2450 | 2487 |
2451 name = vim_strnsave(*arg, end - *arg); | 2488 name = vim_strnsave(*arg, end - *arg); |
2452 if (name == NULL) | 2489 if (name == NULL) |
2453 return FAIL; | 2490 return FAIL; |
2454 | 2491 |
2455 idx = lookup_arg(*arg, len, cctx); | 2492 if (lookup_arg(*arg, len, &idx, &type, &gen_load_outer, cctx) == OK) |
2456 if (idx >= 0) | 2493 { |
2457 { | 2494 if (!gen_load_outer) |
2458 if (cctx->ctx_ufunc->uf_arg_types != NULL) | 2495 gen_load = TRUE; |
2459 type = cctx->ctx_ufunc->uf_arg_types[idx]; | |
2460 else | |
2461 type = &t_any; | |
2462 | |
2463 // Arguments are located above the frame pointer. | |
2464 idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE; | |
2465 if (cctx->ctx_ufunc->uf_va_name != NULL) | |
2466 --idx; | |
2467 gen_load = TRUE; | |
2468 } | |
2469 else if (lookup_vararg(*arg, len, cctx)) | |
2470 { | |
2471 // varargs is always the last argument | |
2472 idx = -STACK_FRAME_SIZE - 1; | |
2473 type = cctx->ctx_ufunc->uf_va_type; | |
2474 gen_load = TRUE; | |
2475 } | 2496 } |
2476 else | 2497 else |
2477 { | 2498 { |
2478 lvar_T *lvar = lookup_local(*arg, len, cctx); | 2499 lvar_T *lvar = lookup_local(*arg, len, cctx); |
2479 | 2500 |