Mercurial > vim
comparison src/vim9compile.c @ 20955:396fe712eb0f v8.2.1029
patch 8.2.1029: Vim9: cannot chain function calls with -> at line start
Commit: https://github.com/vim/vim/commit/23c55273739b2fb09912140e2e03a4b8ff15dd04
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jun 21 16:58:13 2020 +0200
patch 8.2.1029: Vim9: cannot chain function calls with -> at line start
Problem: Vim9: cannot chain function calls with -> at line start.
Solution: Peek ahead for a following line starting with "->". (closes https://github.com/vim/vim/issues/6306)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 21 Jun 2020 17:00:04 +0200 |
parents | 6b4b887a12f0 |
children | 0e01976dfd3b |
comparison
equal
deleted
inserted
replaced
20954:fef8406c5c10 | 20955:396fe712eb0f |
---|---|
2379 } | 2379 } |
2380 ga_clear(&cctx->ctx_imports); | 2380 ga_clear(&cctx->ctx_imports); |
2381 } | 2381 } |
2382 | 2382 |
2383 /* | 2383 /* |
2384 * Return TRUE if "p" points at a "#" but not at "#{". | |
2385 */ | |
2386 static int | |
2387 comment_start(char_u *p) | |
2388 { | |
2389 return p[0] == '#' && p[1] != '{'; | |
2390 } | |
2391 | |
2392 /* | |
2393 * Return a pointer to the next line that isn't empty or only contains a | |
2394 * comment. Skips over white space. | |
2395 * Returns NULL if there is none. | |
2396 */ | |
2397 static char_u * | |
2398 peek_next_line(cctx_T *cctx) | |
2399 { | |
2400 int lnum = cctx->ctx_lnum; | |
2401 | |
2402 while (++lnum < cctx->ctx_ufunc->uf_lines.ga_len) | |
2403 { | |
2404 char_u *line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[lnum]; | |
2405 char_u *p = skipwhite(line); | |
2406 | |
2407 if (*p != NUL && !comment_start(p)) | |
2408 return p; | |
2409 } | |
2410 return NULL; | |
2411 } | |
2412 | |
2413 /* | |
2384 * Get the next line of the function from "cctx". | 2414 * Get the next line of the function from "cctx". |
2415 * Skips over empty lines. Skips over comment lines if "skip_comment" is TRUE. | |
2385 * Returns NULL when at the end. | 2416 * Returns NULL when at the end. |
2386 */ | 2417 */ |
2387 static char_u * | 2418 static char_u * |
2388 next_line_from_context(cctx_T *cctx) | 2419 next_line_from_context(cctx_T *cctx, int skip_comment) |
2389 { | 2420 { |
2390 char_u *line; | 2421 char_u *line; |
2391 | 2422 |
2392 do | 2423 do |
2393 { | 2424 { |
2398 break; | 2429 break; |
2399 } | 2430 } |
2400 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]; | 2431 line = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]; |
2401 cctx->ctx_line_start = line; | 2432 cctx->ctx_line_start = line; |
2402 SOURCING_LNUM = cctx->ctx_lnum + 1; | 2433 SOURCING_LNUM = cctx->ctx_lnum + 1; |
2403 } while (line == NULL || *skipwhite(line) == NUL); | 2434 } while (line == NULL || *skipwhite(line) == NUL |
2435 || (skip_comment && comment_start(skipwhite(line)))); | |
2404 return line; | 2436 return line; |
2405 } | |
2406 | |
2407 /* | |
2408 * Return TRUE if "p" points at a "#" but not at "#{". | |
2409 */ | |
2410 static int | |
2411 comment_start(char_u *p) | |
2412 { | |
2413 return p[0] == '#' && p[1] != '{'; | |
2414 } | 2437 } |
2415 | 2438 |
2416 /* | 2439 /* |
2417 * If "*arg" is at the end of the line, advance to the next line. | 2440 * If "*arg" is at the end of the line, advance to the next line. |
2418 * Also when "whitep" points to white space and "*arg" is on a "#". | 2441 * Also when "whitep" points to white space and "*arg" is on a "#". |
2421 static int | 2444 static int |
2422 may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx) | 2445 may_get_next_line(char_u *whitep, char_u **arg, cctx_T *cctx) |
2423 { | 2446 { |
2424 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg))) | 2447 if (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg))) |
2425 { | 2448 { |
2426 char_u *next = next_line_from_context(cctx); | 2449 char_u *next = next_line_from_context(cctx, TRUE); |
2427 | 2450 |
2428 if (next == NULL) | 2451 if (next == NULL) |
2429 return FAIL; | 2452 return FAIL; |
2430 *arg = skipwhite(next); | 2453 *arg = skipwhite(next); |
2431 } | 2454 } |
2750 char_u *p = *arg; | 2773 char_u *p = *arg; |
2751 char_u *whitep = *arg; | 2774 char_u *whitep = *arg; |
2752 | 2775 |
2753 for (;;) | 2776 for (;;) |
2754 { | 2777 { |
2755 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p))) | 2778 if (may_get_next_line(whitep, &p, cctx) == FAIL) |
2756 { | 2779 goto failret; |
2757 p = next_line_from_context(cctx); | |
2758 if (p == NULL) | |
2759 goto failret; | |
2760 whitep = (char_u *)" "; | |
2761 p = skipwhite(p); | |
2762 } | |
2763 if (*p == ')') | 2780 if (*p == ')') |
2764 { | 2781 { |
2765 *arg = p + 1; | 2782 *arg = p + 1; |
2766 return OK; | 2783 return OK; |
2767 } | 2784 } |
2984 char_u *whitep = *arg + 1; | 3001 char_u *whitep = *arg + 1; |
2985 int count = 0; | 3002 int count = 0; |
2986 | 3003 |
2987 for (;;) | 3004 for (;;) |
2988 { | 3005 { |
2989 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p))) | 3006 if (may_get_next_line(whitep, &p, cctx) == FAIL) |
2990 { | 3007 { |
2991 p = next_line_from_context(cctx); | 3008 semsg(_(e_list_end), *arg); |
2992 if (p == NULL) | 3009 return FAIL; |
2993 { | |
2994 semsg(_(e_list_end), *arg); | |
2995 return FAIL; | |
2996 } | |
2997 whitep = (char_u *)" "; | |
2998 p = skipwhite(p); | |
2999 } | 3010 } |
3000 if (*p == ']') | 3011 if (*p == ']') |
3001 { | 3012 { |
3002 ++p; | 3013 ++p; |
3003 // Allow for following comment, after at least one space. | 3014 // Allow for following comment, after at least one space. |
3110 *arg = skipwhite(*arg + 1); | 3121 *arg = skipwhite(*arg + 1); |
3111 for (;;) | 3122 for (;;) |
3112 { | 3123 { |
3113 char_u *key = NULL; | 3124 char_u *key = NULL; |
3114 | 3125 |
3115 while (**arg == NUL || (literal && **arg == '"') | 3126 if (may_get_next_line(whitep, arg, cctx) == FAIL) |
3116 || (VIM_ISWHITE(*whitep) && comment_start(*arg))) | 3127 { |
3117 { | 3128 *arg = NULL; |
3118 *arg = next_line_from_context(cctx); | 3129 goto failret; |
3119 if (*arg == NULL) | |
3120 goto failret; | |
3121 whitep = (char_u *)" "; | |
3122 *arg = skipwhite(*arg); | |
3123 } | 3130 } |
3124 | 3131 |
3125 if (**arg == '}') | 3132 if (**arg == '}') |
3126 break; | 3133 break; |
3127 | 3134 |
3177 return FAIL; | 3184 return FAIL; |
3178 } | 3185 } |
3179 | 3186 |
3180 whitep = *arg + 1; | 3187 whitep = *arg + 1; |
3181 *arg = skipwhite(*arg + 1); | 3188 *arg = skipwhite(*arg + 1); |
3182 while (**arg == NUL || (VIM_ISWHITE(*whitep) && comment_start(*arg))) | 3189 if (may_get_next_line(whitep, arg, cctx) == FAIL) |
3183 { | 3190 { |
3184 *arg = next_line_from_context(cctx); | 3191 *arg = NULL; |
3185 if (*arg == NULL) | 3192 goto failret; |
3186 goto failret; | |
3187 whitep = (char_u *)" "; | |
3188 *arg = skipwhite(*arg); | |
3189 } | 3193 } |
3190 | 3194 |
3191 if (compile_expr0(arg, cctx) == FAIL) | 3195 if (compile_expr0(arg, cctx) == FAIL) |
3192 return FAIL; | 3196 return FAIL; |
3193 ++count; | 3197 ++count; |
3194 | 3198 |
3195 whitep = *arg; | 3199 whitep = *arg; |
3196 p = skipwhite(*arg); | 3200 *arg = skipwhite(*arg); |
3197 while (*p == NUL || (VIM_ISWHITE(*whitep) && comment_start(p))) | 3201 if (may_get_next_line(whitep, arg, cctx) == FAIL) |
3198 { | 3202 { |
3199 *arg = next_line_from_context(cctx); | 3203 *arg = NULL; |
3200 if (*arg == NULL) | 3204 goto failret; |
3201 goto failret; | |
3202 whitep = (char_u *)" "; | |
3203 *arg = skipwhite(*arg); | |
3204 p = *arg; | |
3205 } | 3205 } |
3206 if (**arg == '}') | 3206 if (**arg == '}') |
3207 break; | 3207 break; |
3208 if (**arg != ',') | 3208 if (**arg != ',') |
3209 { | 3209 { |
3504 char_u *end_leader, | 3504 char_u *end_leader, |
3505 ppconst_T *ppconst) | 3505 ppconst_T *ppconst) |
3506 { | 3506 { |
3507 for (;;) | 3507 for (;;) |
3508 { | 3508 { |
3509 char_u *p = skipwhite(*arg); | |
3510 | |
3511 if (*p == NUL || (VIM_ISWHITE(**arg) && comment_start(p))) | |
3512 { | |
3513 char_u *next = peek_next_line(cctx); | |
3514 | |
3515 // If a following line starts with "->{" or "->X" advance to that | |
3516 // line, so that a line break before "->" is allowed. | |
3517 if (next != NULL && next[0] == '-' && next[1] == '>' | |
3518 && (next[2] == '{' || ASCII_ISALPHA(next[2]))) | |
3519 { | |
3520 next = next_line_from_context(cctx, TRUE); | |
3521 if (next == NULL) | |
3522 return FAIL; | |
3523 *arg = skipwhite(next); | |
3524 } | |
3525 } | |
3526 | |
3509 if (**arg == '(') | 3527 if (**arg == '(') |
3510 { | 3528 { |
3511 garray_T *stack = &cctx->ctx_type_stack; | 3529 garray_T *stack = &cctx->ctx_type_stack; |
3512 type_T *type; | 3530 type_T *type; |
3513 int argcount = 0; | 3531 int argcount = 0; |
3524 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL) | 3542 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL) |
3525 return FAIL; | 3543 return FAIL; |
3526 } | 3544 } |
3527 else if (**arg == '-' && (*arg)[1] == '>') | 3545 else if (**arg == '-' && (*arg)[1] == '>') |
3528 { | 3546 { |
3529 char_u *p; | |
3530 | |
3531 if (generate_ppconst(cctx, ppconst) == FAIL) | 3547 if (generate_ppconst(cctx, ppconst) == FAIL) |
3532 return FAIL; | 3548 return FAIL; |
3533 | 3549 |
3534 // something->method() | 3550 // something->method() |
3535 // Apply the '!', '-' and '+' first: | 3551 // Apply the '!', '-' and '+' first: |
3568 } | 3584 } |
3569 else if (**arg == '[') | 3585 else if (**arg == '[') |
3570 { | 3586 { |
3571 garray_T *stack = &cctx->ctx_type_stack; | 3587 garray_T *stack = &cctx->ctx_type_stack; |
3572 type_T **typep; | 3588 type_T **typep; |
3573 char_u *p; | |
3574 | 3589 |
3575 // list index: list[123] | 3590 // list index: list[123] |
3576 // dict member: dict[key] | 3591 // dict member: dict[key] |
3577 // TODO: blob index | 3592 // TODO: blob index |
3578 // TODO: more arguments | 3593 // TODO: more arguments |
3616 return FAIL; | 3631 return FAIL; |
3617 } | 3632 } |
3618 } | 3633 } |
3619 else if (**arg == '.' && (*arg)[1] != '.') | 3634 else if (**arg == '.' && (*arg)[1] != '.') |
3620 { | 3635 { |
3621 char_u *p; | |
3622 | |
3623 if (generate_ppconst(cctx, ppconst) == FAIL) | 3636 if (generate_ppconst(cctx, ppconst) == FAIL) |
3624 return FAIL; | 3637 return FAIL; |
3625 | 3638 |
3626 ++*arg; | 3639 ++*arg; |
3627 if (may_get_next_line(*arg, arg, cctx) == FAIL) | 3640 if (may_get_next_line(*arg, arg, cctx) == FAIL) |
6694 semsg(_("E488: Trailing characters: %s"), line); | 6707 semsg(_("E488: Trailing characters: %s"), line); |
6695 goto erret; | 6708 goto erret; |
6696 } | 6709 } |
6697 else | 6710 else |
6698 { | 6711 { |
6699 line = next_line_from_context(&cctx); | 6712 line = next_line_from_context(&cctx, FALSE); |
6700 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len) | 6713 if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len) |
6701 // beyond the last line | 6714 // beyond the last line |
6702 break; | 6715 break; |
6703 } | 6716 } |
6704 emsg_before = called_emsg; | 6717 emsg_before = called_emsg; |