comparison src/eval.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 667192c5938b
children ad13736a1783
comparison
equal deleted inserted replaced
21207:2a1156d4950f 21208:09377fd59b2e
388 int res; 388 int res;
389 int vim9script = current_sctx.sc_version == SCRIPT_VERSION_VIM9; 389 int vim9script = current_sctx.sc_version == SCRIPT_VERSION_VIM9;
390 garray_T *gap = &evalarg->eval_ga; 390 garray_T *gap = &evalarg->eval_ga;
391 int save_flags = evalarg == NULL ? 0 : evalarg->eval_flags; 391 int save_flags = evalarg == NULL ? 0 : evalarg->eval_flags;
392 392
393 if (vim9script && evalarg->eval_cookie != NULL) 393 if (vim9script
394 && (evalarg->eval_cookie != NULL || evalarg->eval_cctx != NULL))
394 { 395 {
395 ga_init2(gap, sizeof(char_u *), 10); 396 ga_init2(gap, sizeof(char_u *), 10);
397 // leave room for "start"
396 if (ga_grow(gap, 1) == OK) 398 if (ga_grow(gap, 1) == OK)
397 // leave room for "start"
398 ++gap->ga_len; 399 ++gap->ga_len;
399 } 400 }
400 401
401 // Don't evaluate the expression. 402 // Don't evaluate the expression.
402 if (evalarg != NULL) 403 if (evalarg != NULL)
404 *end = skipwhite(*end); 405 *end = skipwhite(*end);
405 res = eval1(end, &rettv, evalarg); 406 res = eval1(end, &rettv, evalarg);
406 if (evalarg != NULL) 407 if (evalarg != NULL)
407 evalarg->eval_flags = save_flags; 408 evalarg->eval_flags = save_flags;
408 409
409 if (vim9script && evalarg->eval_cookie != NULL 410 if (vim9script
410 && evalarg->eval_ga.ga_len > 1) 411 && (evalarg->eval_cookie != NULL || evalarg->eval_cctx != NULL))
411 { 412 {
412 char_u *p; 413 if (evalarg->eval_ga.ga_len == 1)
413 size_t endoff = STRLEN(*end); 414 {
414 415 // just one line, no need to concatenate
415 // Line breaks encountered, concatenate all the lines. 416 ga_clear(gap);
416 *((char_u **)gap->ga_data) = *start; 417 gap->ga_itemsize = 0;
417 p = ga_concat_strings(gap, ""); 418 }
418 *((char_u **)gap->ga_data) = NULL; 419 else
419 ga_clear_strings(gap); 420 {
420 gap->ga_itemsize = 0; 421 char_u *p;
421 if (p == NULL) 422 size_t endoff = STRLEN(*end);
422 return FAIL; 423
423 *start = p; 424 // Line breaks encountered, concatenate all the lines.
424 vim_free(evalarg->eval_tofree); 425 *((char_u **)gap->ga_data) = *start;
425 evalarg->eval_tofree = p; 426 p = ga_concat_strings(gap, "");
426 // Compute "end" relative to the end. 427
427 *end = *start + STRLEN(*start) - endoff; 428 // free the lines only when using getsourceline()
429 if (evalarg->eval_cookie != NULL)
430 {
431 *((char_u **)gap->ga_data) = NULL;
432 ga_clear_strings(gap);
433 }
434 else
435 ga_clear(gap);
436 gap->ga_itemsize = 0;
437 if (p == NULL)
438 return FAIL;
439 *start = p;
440 vim_free(evalarg->eval_tofree);
441 evalarg->eval_tofree = p;
442 // Compute "end" relative to the end.
443 *end = *start + STRLEN(*start) - endoff;
444 }
428 } 445 }
429 446
430 return res; 447 return res;
431 } 448 }
432 449
433 /* 450 /*
434 * Top level evaluation function, returning a string. 451 * Top level evaluation function, returning a string. Does not handle line
452 * breaks.
435 * When "convert" is TRUE convert a List into a sequence of lines and convert 453 * When "convert" is TRUE convert a List into a sequence of lines and convert
436 * a Float to a String. 454 * a Float to a String.
437 * Return pointer to allocated memory, or NULL for failure. 455 * Return pointer to allocated memory, or NULL for failure.
438 */ 456 */
439 char_u * 457 char_u *
1876 eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext) 1894 eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
1877 { 1895 {
1878 *getnext = FALSE; 1896 *getnext = FALSE;
1879 if (current_sctx.sc_version == SCRIPT_VERSION_VIM9 1897 if (current_sctx.sc_version == SCRIPT_VERSION_VIM9
1880 && evalarg != NULL 1898 && evalarg != NULL
1881 && evalarg->eval_cookie != NULL 1899 && (evalarg->eval_cookie != NULL || evalarg->eval_cctx != NULL)
1882 && (*arg == NUL || (VIM_ISWHITE(arg[-1]) 1900 && (*arg == NUL || (VIM_ISWHITE(arg[-1])
1883 && *arg == '#' && arg[1] != '{'))) 1901 && *arg == '#' && arg[1] != '{')))
1884 { 1902 {
1885 char_u *p = getline_peek(evalarg->eval_getline, evalarg->eval_cookie); 1903 char_u *p;
1904
1905 if (evalarg->eval_cookie != NULL)
1906 p = getline_peek(evalarg->eval_getline, evalarg->eval_cookie);
1907 else
1908 p = peek_next_line_from_context(evalarg->eval_cctx);
1886 1909
1887 if (p != NULL) 1910 if (p != NULL)
1888 { 1911 {
1889 *getnext = TRUE; 1912 *getnext = TRUE;
1890 return skipwhite(p); 1913 return skipwhite(p);
1900 eval_next_line(evalarg_T *evalarg) 1923 eval_next_line(evalarg_T *evalarg)
1901 { 1924 {
1902 garray_T *gap = &evalarg->eval_ga; 1925 garray_T *gap = &evalarg->eval_ga;
1903 char_u *line; 1926 char_u *line;
1904 1927
1905 line = evalarg->eval_getline(0, evalarg->eval_cookie, 0, TRUE); 1928 if (evalarg->eval_cookie != NULL)
1929 line = evalarg->eval_getline(0, evalarg->eval_cookie, 0, TRUE);
1930 else
1931 line = next_line_from_context(evalarg->eval_cctx, TRUE);
1906 ++evalarg->eval_break_count; 1932 ++evalarg->eval_break_count;
1907 if (gap->ga_itemsize > 0 && ga_grow(gap, 1) == OK) 1933 if (gap->ga_itemsize > 0 && ga_grow(gap, 1) == OK)
1908 { 1934 {
1909 // Going to concatenate the lines after parsing. 1935 // Going to concatenate the lines after parsing.
1910 ((char_u **)gap->ga_data)[gap->ga_len] = line; 1936 ((char_u **)gap->ga_data)[gap->ga_len] = line;
5032 int evaluate = evalarg != NULL 5058 int evaluate = evalarg != NULL
5033 && (evalarg->eval_flags & EVAL_EVALUATE); 5059 && (evalarg->eval_flags & EVAL_EVALUATE);
5034 int ret = OK; 5060 int ret = OK;
5035 dict_T *selfdict = NULL; 5061 dict_T *selfdict = NULL;
5036 int check_white = TRUE; 5062 int check_white = TRUE;
5037 5063 int getnext;
5038 // When at the end of the line and ".name" follows in the next line then 5064 char_u *p;
5039 // consume the line break. Only when rettv is a dict. 5065
5040 if (rettv->v_type == VAR_DICT) 5066 while (ret == OK)
5041 { 5067 {
5042 int getnext; 5068 // When at the end of the line and ".name" or "->{" or "->X" follows in
5043 char_u *p = eval_next_non_blank(*arg, evalarg, &getnext); 5069 // the next line then consume the line break.
5044 5070 p = eval_next_non_blank(*arg, evalarg, &getnext);
5045 if (getnext && *p == '.' && ASCII_ISALPHA(p[1])) 5071 if (getnext
5072 && ((rettv->v_type == VAR_DICT && *p == '.'
5073 && ASCII_ISALPHA(p[1]))
5074 || (*p == '-' && p[1] == '>'
5075 && (p[2] == '{' || ASCII_ISALPHA(p[2])))))
5046 { 5076 {
5047 *arg = eval_next_line(evalarg); 5077 *arg = eval_next_line(evalarg);
5048 check_white = FALSE; 5078 check_white = FALSE;
5049 } 5079 }
5050 } 5080
5051 5081 if ((**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
5052 // "." is ".name" lookup when we found a dict or when evaluating and 5082 || rettv->v_type == VAR_PARTIAL))
5053 // scriptversion is at least 2, where string concatenation is "..". 5083 && (!check_white || !VIM_ISWHITE(*(*arg - 1))))
5054 while (ret == OK
5055 && (((**arg == '['
5056 || (**arg == '.' && (rettv->v_type == VAR_DICT
5057 || (!evaluate
5058 && (*arg)[1] != '.'
5059 && current_sctx.sc_version >= 2)))
5060 || (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
5061 || rettv->v_type == VAR_PARTIAL)))
5062 && (!check_white || !VIM_ISWHITE(*(*arg - 1))))
5063 || (**arg == '-' && (*arg)[1] == '>')))
5064 {
5065 if (**arg == '(')
5066 { 5084 {
5067 ret = call_func_rettv(arg, evalarg, rettv, evaluate, 5085 ret = call_func_rettv(arg, evalarg, rettv, evaluate,
5068 selfdict, NULL); 5086 selfdict, NULL);
5069 5087
5070 // Stop the expression evaluation when immediately aborting on 5088 // Stop the expression evaluation when immediately aborting on
5077 ret = FAIL; 5095 ret = FAIL;
5078 } 5096 }
5079 dict_unref(selfdict); 5097 dict_unref(selfdict);
5080 selfdict = NULL; 5098 selfdict = NULL;
5081 } 5099 }
5082 else if (**arg == '-') 5100 else if (**arg == '-' && (*arg)[1] == '>')
5083 { 5101 {
5084 if (ret == OK) 5102 if (ret == OK)
5085 { 5103 {
5086 if ((*arg)[2] == '{') 5104 if ((*arg)[2] == '{')
5087 // expr->{lambda}() 5105 // expr->{lambda}()
5089 else 5107 else
5090 // expr->name() 5108 // expr->name()
5091 ret = eval_method(arg, rettv, evalarg, verbose); 5109 ret = eval_method(arg, rettv, evalarg, verbose);
5092 } 5110 }
5093 } 5111 }
5094 else // **arg == '[' || **arg == '.' 5112 // "." is ".name" lookup when we found a dict or when evaluating and
5113 // scriptversion is at least 2, where string concatenation is "..".
5114 else if (**arg == '['
5115 || (**arg == '.' && (rettv->v_type == VAR_DICT
5116 || (!evaluate
5117 && (*arg)[1] != '.'
5118 && current_sctx.sc_version >= 2))))
5095 { 5119 {
5096 dict_unref(selfdict); 5120 dict_unref(selfdict);
5097 if (rettv->v_type == VAR_DICT) 5121 if (rettv->v_type == VAR_DICT)
5098 { 5122 {
5099 selfdict = rettv->vval.v_dict; 5123 selfdict = rettv->vval.v_dict;
5106 { 5130 {
5107 clear_tv(rettv); 5131 clear_tv(rettv);
5108 ret = FAIL; 5132 ret = FAIL;
5109 } 5133 }
5110 } 5134 }
5135 else
5136 break;
5111 } 5137 }
5112 5138
5113 // Turn "dict.Func" into a partial for "Func" bound to "dict". 5139 // Turn "dict.Func" into a partial for "Func" bound to "dict".
5114 // Don't do this when "Func" is already a partial that was bound 5140 // Don't do this when "Func" is already a partial that was bound
5115 // explicitly (pt_auto is FALSE). 5141 // explicitly (pt_auto is FALSE).