comparison src/vim9compile.c @ 21208:09377fd59b2e v8.2.1155

patch 8.2.1155: Vim9: cannot handle line break inside lambda Commit: https://github.com/vim/vim/commit/7a4b8980ea5ecaea061caae7816ea62cc4940011 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Jul 8 17:36:21 2020 +0200 patch 8.2.1155: Vim9: cannot handle line break inside lambda Problem: Vim9: cannot handle line break inside lambda. Solution: Pass the compilation context through. (closes https://github.com/vim/vim/issues/6407, closes https://github.com/vim/vim/issues/6409)
author Bram Moolenaar <Bram@vim.org>
date Wed, 08 Jul 2020 17:45:06 +0200
parents 1a4e22aa2eb3
children 44611891e22c
comparison
equal deleted inserted replaced
21207:2a1156d4950f 21208:09377fd59b2e
2395 /* 2395 /*
2396 * Return a pointer to the next line that isn't empty or only contains a 2396 * Return a pointer to the next line that isn't empty or only contains a
2397 * comment. Skips over white space. 2397 * comment. Skips over white space.
2398 * Returns NULL if there is none. 2398 * Returns NULL if there is none.
2399 */ 2399 */
2400 static char_u * 2400 char_u *
2401 peek_next_line(cctx_T *cctx) 2401 peek_next_line_from_context(cctx_T *cctx)
2402 { 2402 {
2403 int lnum = cctx->ctx_lnum; 2403 int lnum = cctx->ctx_lnum;
2404 2404
2405 while (++lnum < cctx->ctx_ufunc->uf_lines.ga_len) 2405 while (++lnum < cctx->ctx_ufunc->uf_lines.ga_len)
2406 { 2406 {
2428 char_u *p = skipwhite(arg); 2428 char_u *p = skipwhite(arg);
2429 2429
2430 *nextp = NULL; 2430 *nextp = NULL;
2431 if (*p == NUL || (VIM_ISWHITE(*arg) && comment_start(p))) 2431 if (*p == NUL || (VIM_ISWHITE(*arg) && comment_start(p)))
2432 { 2432 {
2433 *nextp = peek_next_line(cctx); 2433 *nextp = peek_next_line_from_context(cctx);
2434 if (*nextp != NULL) 2434 if (*nextp != NULL)
2435 return *nextp; 2435 return *nextp;
2436 } 2436 }
2437 return p; 2437 return p;
2438 } 2438 }
2440 /* 2440 /*
2441 * Get the next line of the function from "cctx". 2441 * Get the next line of the function from "cctx".
2442 * Skips over empty lines. Skips over comment lines if "skip_comment" is TRUE. 2442 * Skips over empty lines. Skips over comment lines if "skip_comment" is TRUE.
2443 * Returns NULL when at the end. 2443 * Returns NULL when at the end.
2444 */ 2444 */
2445 static char_u * 2445 char_u *
2446 next_line_from_context(cctx_T *cctx, int skip_comment) 2446 next_line_from_context(cctx_T *cctx, int skip_comment)
2447 { 2447 {
2448 char_u *line; 2448 char_u *line;
2449 2449
2450 do 2450 do
3077 static int 3077 static int
3078 compile_lambda(char_u **arg, cctx_T *cctx) 3078 compile_lambda(char_u **arg, cctx_T *cctx)
3079 { 3079 {
3080 typval_T rettv; 3080 typval_T rettv;
3081 ufunc_T *ufunc; 3081 ufunc_T *ufunc;
3082 evalarg_T evalarg;
3083
3084 CLEAR_FIELD(evalarg);
3085 evalarg.eval_flags = EVAL_EVALUATE;
3086 evalarg.eval_cctx = cctx;
3082 3087
3083 // Get the funcref in "rettv". 3088 // Get the funcref in "rettv".
3084 if (get_lambda_tv(arg, &rettv, &EVALARG_EVALUATE) != OK) 3089 if (get_lambda_tv(arg, &rettv, &evalarg) != OK)
3085 return FAIL; 3090 return FAIL;
3086 3091
3087 ufunc = rettv.vval.v_partial->pt_func; 3092 ufunc = rettv.vval.v_partial->pt_func;
3088 ++ufunc->uf_refcount; 3093 ++ufunc->uf_refcount;
3089 clear_tv(&rettv); 3094 clear_tv(&rettv);
3533 return OK; 3538 return OK;
3534 } 3539 }
3535 3540
3536 /* 3541 /*
3537 * Compile whatever comes after "name" or "name()". 3542 * Compile whatever comes after "name" or "name()".
3543 * Advances "*arg" only when something was recognized.
3538 */ 3544 */
3539 static int 3545 static int
3540 compile_subscript( 3546 compile_subscript(
3541 char_u **arg, 3547 char_u **arg,
3542 cctx_T *cctx, 3548 cctx_T *cctx,
3548 { 3554 {
3549 char_u *p = skipwhite(*arg); 3555 char_u *p = skipwhite(*arg);
3550 3556
3551 if (*p == NUL || (VIM_ISWHITE(**arg) && comment_start(p))) 3557 if (*p == NUL || (VIM_ISWHITE(**arg) && comment_start(p)))
3552 { 3558 {
3553 char_u *next = peek_next_line(cctx); 3559 char_u *next = peek_next_line_from_context(cctx);
3554 3560
3555 // If a following line starts with "->{" or "->X" advance to that 3561 // If a following line starts with "->{" or "->X" advance to that
3556 // line, so that a line break before "->" is allowed. 3562 // line, so that a line break before "->" is allowed.
3557 if (next != NULL && next[0] == '-' && next[1] == '>' 3563 if (next != NULL && next[0] == '-' && next[1] == '>'
3558 && (next[2] == '{' || ASCII_ISALPHA(next[2]))) 3564 && (next[2] == '{' || ASCII_ISALPHA(next[2])))
3559 { 3565 {
3560 next = next_line_from_context(cctx, TRUE); 3566 next = next_line_from_context(cctx, TRUE);
3561 if (next == NULL) 3567 if (next == NULL)
3562 return FAIL; 3568 return FAIL;
3563 *arg = skipwhite(next); 3569 *arg = next;
3564 } 3570 p = skipwhite(*arg);
3565 } 3571 }
3566 3572 }
3567 if (**arg == '(') 3573
3574 if (*p == '(')
3568 { 3575 {
3569 garray_T *stack = &cctx->ctx_type_stack; 3576 garray_T *stack = &cctx->ctx_type_stack;
3570 type_T *type; 3577 type_T *type;
3571 int argcount = 0; 3578 int argcount = 0;
3572 3579
3574 return FAIL; 3581 return FAIL;
3575 3582
3576 // funcref(arg) 3583 // funcref(arg)
3577 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; 3584 type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
3578 3585
3579 *arg = skipwhite(*arg + 1); 3586 *arg = skipwhite(p + 1);
3580 if (compile_arguments(arg, cctx, &argcount) == FAIL) 3587 if (compile_arguments(arg, cctx, &argcount) == FAIL)
3581 return FAIL; 3588 return FAIL;
3582 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL) 3589 if (generate_PCALL(cctx, argcount, end_leader, type, TRUE) == FAIL)
3583 return FAIL; 3590 return FAIL;
3584 } 3591 }
3585 else if (**arg == '-' && (*arg)[1] == '>') 3592 else if (*p == '-' && p[1] == '>')
3586 { 3593 {
3587 if (generate_ppconst(cctx, ppconst) == FAIL) 3594 if (generate_ppconst(cctx, ppconst) == FAIL)
3588 return FAIL; 3595 return FAIL;
3589 3596
3590 // something->method() 3597 // something->method()
3592 // -1.0->func() works like (-1.0)->func() 3599 // -1.0->func() works like (-1.0)->func()
3593 if (compile_leader(cctx, *start_leader, end_leader) == FAIL) 3600 if (compile_leader(cctx, *start_leader, end_leader) == FAIL)
3594 return FAIL; 3601 return FAIL;
3595 *start_leader = end_leader; // don't apply again later 3602 *start_leader = end_leader; // don't apply again later
3596 3603
3597 p = *arg + 2; 3604 p += 2;
3598 *arg = skipwhite(p); 3605 *arg = skipwhite(p);
3599 if (may_get_next_line(p, arg, cctx) == FAIL) 3606 if (may_get_next_line(p, arg, cctx) == FAIL)
3600 return FAIL; 3607 return FAIL;
3601 if (**arg == '{') 3608 if (**arg == '{')
3602 { 3609 {
3620 // TODO: base value may not be the first argument 3627 // TODO: base value may not be the first argument
3621 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL) 3628 if (compile_call(arg, p - *arg, cctx, ppconst, 1) == FAIL)
3622 return FAIL; 3629 return FAIL;
3623 } 3630 }
3624 } 3631 }
3625 else if (**arg == '[') 3632 else if (*p == '[')
3626 { 3633 {
3627 garray_T *stack = &cctx->ctx_type_stack; 3634 garray_T *stack = &cctx->ctx_type_stack;
3628 type_T **typep; 3635 type_T **typep;
3629 3636
3630 // list index: list[123] 3637 // list index: list[123]
3633 // TODO: more arguments 3640 // TODO: more arguments
3634 // TODO: recognize list or dict at runtime 3641 // TODO: recognize list or dict at runtime
3635 if (generate_ppconst(cctx, ppconst) == FAIL) 3642 if (generate_ppconst(cctx, ppconst) == FAIL)
3636 return FAIL; 3643 return FAIL;
3637 3644
3638 p = *arg + 1; 3645 ++p;
3639 *arg = skipwhite(p); 3646 *arg = skipwhite(p);
3640 if (may_get_next_line(p, arg, cctx) == FAIL) 3647 if (may_get_next_line(p, arg, cctx) == FAIL)
3641 return FAIL; 3648 return FAIL;
3642 if (compile_expr0(arg, cctx) == FAIL) 3649 if (compile_expr0(arg, cctx) == FAIL)
3643 return FAIL; 3650 return FAIL;
3669 { 3676 {
3670 emsg(_(e_listdictblobreq)); 3677 emsg(_(e_listdictblobreq));
3671 return FAIL; 3678 return FAIL;
3672 } 3679 }
3673 } 3680 }
3674 else if (**arg == '.' && (*arg)[1] != '.') 3681 else if (*p == '.' && p[1] != '.')
3675 { 3682 {
3676 if (generate_ppconst(cctx, ppconst) == FAIL) 3683 if (generate_ppconst(cctx, ppconst) == FAIL)
3677 return FAIL; 3684 return FAIL;
3678 3685
3679 ++*arg; 3686 *arg = p + 1;
3680 if (may_get_next_line(*arg, arg, cctx) == FAIL) 3687 if (may_get_next_line(*arg, arg, cctx) == FAIL)
3681 return FAIL; 3688 return FAIL;
3682 // dictionary member: dict.name 3689 // dictionary member: dict.name
3683 p = *arg; 3690 p = *arg;
3684 if (eval_isnamec1(*p)) 3691 if (eval_isnamec1(*p))