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