Mercurial > vim
comparison src/userfunc.c @ 20279:49b50843e725 v8.2.0695
patch 8.2.0695: Vim9: cannot define a function inside a function
Commit: https://github.com/vim/vim/commit/04b12697838b232b8b17c553ccc74cf1f1bdb81c
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon May 4 23:24:44 2020 +0200
patch 8.2.0695: Vim9: cannot define a function inside a function
Problem: Vim9: cannot define a function inside a function.
Solution: Initial support for :def inside :def.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 04 May 2020 23:30:04 +0200 |
parents | 683c2da4982b |
children | 7587d892c00c |
comparison
equal
deleted
inserted
replaced
20278:4148ba869078 | 20279:49b50843e725 |
---|---|
327 } | 327 } |
328 } | 328 } |
329 } | 329 } |
330 | 330 |
331 /* | 331 /* |
332 * Get a name for a lambda. Returned in static memory. | |
333 */ | |
334 char_u * | |
335 get_lambda_name(void) | |
336 { | |
337 static char_u name[30]; | |
338 static int lambda_no = 0; | |
339 | |
340 sprintf((char*)name, "<lambda>%d", ++lambda_no); | |
341 return name; | |
342 } | |
343 | |
344 /* | |
332 * Parse a lambda expression and get a Funcref from "*arg". | 345 * Parse a lambda expression and get a Funcref from "*arg". |
333 * Return OK or FAIL. Returns NOTDONE for dict or {expr}. | 346 * Return OK or FAIL. Returns NOTDONE for dict or {expr}. |
334 */ | 347 */ |
335 int | 348 int |
336 get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate) | 349 get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate) |
342 partial_T *pt = NULL; | 355 partial_T *pt = NULL; |
343 int varargs; | 356 int varargs; |
344 int ret; | 357 int ret; |
345 char_u *start = skipwhite(*arg + 1); | 358 char_u *start = skipwhite(*arg + 1); |
346 char_u *s, *e; | 359 char_u *s, *e; |
347 static int lambda_no = 0; | |
348 int *old_eval_lavars = eval_lavars_used; | 360 int *old_eval_lavars = eval_lavars_used; |
349 int eval_lavars = FALSE; | 361 int eval_lavars = FALSE; |
350 | 362 |
351 ga_init(&newargs); | 363 ga_init(&newargs); |
352 ga_init(&newlines); | 364 ga_init(&newlines); |
390 | 402 |
391 if (evaluate) | 403 if (evaluate) |
392 { | 404 { |
393 int len, flags = 0; | 405 int len, flags = 0; |
394 char_u *p; | 406 char_u *p; |
395 char_u name[20]; | 407 char_u *name = get_lambda_name(); |
396 | |
397 sprintf((char*)name, "<lambda>%d", ++lambda_no); | |
398 | 408 |
399 fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); | 409 fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); |
400 if (fp == NULL) | 410 if (fp == NULL) |
401 goto errret; | 411 goto errret; |
402 fp->uf_dfunc_idx = -1; | 412 fp->uf_dfunc_idx = -1; |
2362 } | 2372 } |
2363 return NULL; | 2373 return NULL; |
2364 } | 2374 } |
2365 | 2375 |
2366 /* | 2376 /* |
2367 * ":function" | 2377 * ":function" also supporting nested ":def". |
2368 */ | 2378 * Returns a pointer to the function or NULL if no function defined. |
2369 void | 2379 */ |
2370 ex_function(exarg_T *eap) | 2380 ufunc_T * |
2381 def_function(exarg_T *eap, char_u *name_arg, void *context) | |
2371 { | 2382 { |
2372 char_u *theline; | 2383 char_u *theline; |
2373 char_u *line_to_free = NULL; | 2384 char_u *line_to_free = NULL; |
2374 int j; | 2385 int j; |
2375 int c; | 2386 int c; |
2376 int saved_did_emsg; | 2387 int saved_did_emsg; |
2377 int saved_wait_return = need_wait_return; | 2388 int saved_wait_return = need_wait_return; |
2378 char_u *name = NULL; | 2389 char_u *name = name_arg; |
2379 int is_global = FALSE; | 2390 int is_global = FALSE; |
2380 char_u *p; | 2391 char_u *p; |
2381 char_u *arg; | 2392 char_u *arg; |
2382 char_u *line_arg = NULL; | 2393 char_u *line_arg = NULL; |
2383 garray_T newargs; | 2394 garray_T newargs; |
2385 garray_T default_args; | 2396 garray_T default_args; |
2386 garray_T newlines; | 2397 garray_T newlines; |
2387 int varargs = FALSE; | 2398 int varargs = FALSE; |
2388 int flags = 0; | 2399 int flags = 0; |
2389 char_u *ret_type = NULL; | 2400 char_u *ret_type = NULL; |
2390 ufunc_T *fp; | 2401 ufunc_T *fp = NULL; |
2391 int overwrite = FALSE; | 2402 int overwrite = FALSE; |
2392 int indent; | 2403 int indent; |
2393 int nesting; | 2404 int nesting; |
2394 #define MAX_FUNC_NESTING 50 | 2405 #define MAX_FUNC_NESTING 50 |
2395 char nesting_def[MAX_FUNC_NESTING]; | 2406 char nesting_def[MAX_FUNC_NESTING]; |
2427 list_func_head(fp, FALSE); | 2438 list_func_head(fp, FALSE); |
2428 } | 2439 } |
2429 } | 2440 } |
2430 } | 2441 } |
2431 eap->nextcmd = check_nextcmd(eap->arg); | 2442 eap->nextcmd = check_nextcmd(eap->arg); |
2432 return; | 2443 return NULL; |
2433 } | 2444 } |
2434 | 2445 |
2435 /* | 2446 /* |
2436 * ":function /pat": list functions matching pattern. | 2447 * ":function /pat": list functions matching pattern. |
2437 */ | 2448 */ |
2467 } | 2478 } |
2468 } | 2479 } |
2469 if (*p == '/') | 2480 if (*p == '/') |
2470 ++p; | 2481 ++p; |
2471 eap->nextcmd = check_nextcmd(p); | 2482 eap->nextcmd = check_nextcmd(p); |
2472 return; | 2483 return NULL; |
2473 } | 2484 } |
2474 | 2485 |
2475 ga_init(&newargs); | 2486 ga_init(&newargs); |
2476 ga_init(&argtypes); | 2487 ga_init(&argtypes); |
2477 ga_init(&default_args); | 2488 ga_init(&default_args); |
2491 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL | 2502 * "fudi.fd_di" set, "fudi.fd_newkey" == NULL |
2492 * s:func script-local function name | 2503 * s:func script-local function name |
2493 * g:func global function name, same as "func" | 2504 * g:func global function name, same as "func" |
2494 */ | 2505 */ |
2495 p = eap->arg; | 2506 p = eap->arg; |
2496 name = trans_function_name(&p, &is_global, eap->skip, | 2507 if (name_arg != NULL) |
2508 { | |
2509 // nested function, argument is (args). | |
2510 paren = TRUE; | |
2511 CLEAR_FIELD(fudi); | |
2512 } | |
2513 else | |
2514 { | |
2515 name = trans_function_name(&p, &is_global, eap->skip, | |
2497 TFN_NO_AUTOLOAD, &fudi, NULL); | 2516 TFN_NO_AUTOLOAD, &fudi, NULL); |
2498 paren = (vim_strchr(p, '(') != NULL); | 2517 paren = (vim_strchr(p, '(') != NULL); |
2499 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip) | 2518 if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip) |
2500 { | 2519 { |
2501 /* | 2520 /* |
2502 * Return on an invalid expression in braces, unless the expression | 2521 * Return on an invalid expression in braces, unless the expression |
2503 * evaluation has been cancelled due to an aborting error, an | 2522 * evaluation has been cancelled due to an aborting error, an |
2504 * interrupt, or an exception. | 2523 * interrupt, or an exception. |
2505 */ | 2524 */ |
2506 if (!aborting()) | 2525 if (!aborting()) |
2507 { | 2526 { |
2508 if (!eap->skip && fudi.fd_newkey != NULL) | 2527 if (!eap->skip && fudi.fd_newkey != NULL) |
2509 semsg(_(e_dictkey), fudi.fd_newkey); | 2528 semsg(_(e_dictkey), fudi.fd_newkey); |
2510 vim_free(fudi.fd_newkey); | 2529 vim_free(fudi.fd_newkey); |
2511 return; | 2530 return NULL; |
2512 } | 2531 } |
2513 else | 2532 else |
2514 eap->skip = TRUE; | 2533 eap->skip = TRUE; |
2534 } | |
2515 } | 2535 } |
2516 | 2536 |
2517 // An error in a function call during evaluation of an expression in magic | 2537 // An error in a function call during evaluation of an expression in magic |
2518 // braces should not cause the function not to be defined. | 2538 // braces should not cause the function not to be defined. |
2519 saved_did_emsg = did_emsg; | 2539 saved_did_emsg = did_emsg; |
2594 } | 2614 } |
2595 p = skipwhite(p + 1); | 2615 p = skipwhite(p + 1); |
2596 | 2616 |
2597 ga_init2(&newlines, (int)sizeof(char_u *), 3); | 2617 ga_init2(&newlines, (int)sizeof(char_u *), 3); |
2598 | 2618 |
2599 if (!eap->skip) | 2619 if (!eap->skip && name_arg == NULL) |
2600 { | 2620 { |
2601 // Check the name of the function. Unless it's a dictionary function | 2621 // Check the name of the function. Unless it's a dictionary function |
2602 // (that we are overwriting). | 2622 // (that we are overwriting). |
2603 if (name != NULL) | 2623 if (name != NULL) |
2604 arg = name; | 2624 arg = name; |
3253 is_export = FALSE; | 3273 is_export = FALSE; |
3254 } | 3274 } |
3255 | 3275 |
3256 // ":def Func()" needs to be compiled | 3276 // ":def Func()" needs to be compiled |
3257 if (eap->cmdidx == CMD_def) | 3277 if (eap->cmdidx == CMD_def) |
3258 compile_def_function(fp, FALSE, NULL); | 3278 compile_def_function(fp, FALSE, context); |
3259 | 3279 |
3260 goto ret_free; | 3280 goto ret_free; |
3261 | 3281 |
3262 erret: | 3282 erret: |
3263 ga_clear_strings(&newargs); | 3283 ga_clear_strings(&newargs); |
3267 ret_free: | 3287 ret_free: |
3268 ga_clear_strings(&argtypes); | 3288 ga_clear_strings(&argtypes); |
3269 vim_free(skip_until); | 3289 vim_free(skip_until); |
3270 vim_free(line_to_free); | 3290 vim_free(line_to_free); |
3271 vim_free(fudi.fd_newkey); | 3291 vim_free(fudi.fd_newkey); |
3272 vim_free(name); | 3292 if (name != name_arg) |
3293 vim_free(name); | |
3273 vim_free(ret_type); | 3294 vim_free(ret_type); |
3274 did_emsg |= saved_did_emsg; | 3295 did_emsg |= saved_did_emsg; |
3275 need_wait_return |= saved_wait_return; | 3296 need_wait_return |= saved_wait_return; |
3297 | |
3298 return fp; | |
3299 } | |
3300 | |
3301 /* | |
3302 * ":function" | |
3303 */ | |
3304 void | |
3305 ex_function(exarg_T *eap) | |
3306 { | |
3307 def_function(eap, NULL, NULL); | |
3276 } | 3308 } |
3277 | 3309 |
3278 /* | 3310 /* |
3279 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case). | 3311 * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case). |
3280 * Return 2 if "p" starts with "s:". | 3312 * Return 2 if "p" starts with "s:". |